Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 36 additions & 32 deletions sqlalchemy_utils/functions/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -562,35 +562,37 @@ def create_database(url, encoding='utf8', template=None):
else:
engine = sa.create_engine(url)

if dialect_name == 'postgresql':
if not template:
template = 'template1'

with engine.begin() as conn:
text = "CREATE DATABASE {} ENCODING '{}' TEMPLATE {}".format(
quote(conn, database), encoding, quote(conn, template)
)
conn.execute(sa.text(text))
try:
if dialect_name == 'postgresql':
if not template:
template = 'template1'
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This kicks off a try/except block that is larger than it should be.

I recommend modifying this so that the conditionals exclusively determine what the text variable should be.

text = ''
if dialect_name == 'postgresql':
    if not template:
        template = 'template1'
    text = "CREATE DATABASE {} CHARACTER SET = '{}'".format(
        quote(conn, database), encoding
    )
elif dialect_name == 'mysql':
    ...
    text = ...
elif dialect_name == 'sqlite' and database != ':memory:':
    if database:
        text = 'CREATE TABLE DB(id int); DROP TABLE DB;'
else:
    text = f'CREATE DATABASE {quote(conn, database)}'

and then reduce the try/except block to something like this, which accommodates the possibility that text is an empty string.

if text:
    try:
        with engine.begin() as conn:
            conn.execute(sa.text(text))
    finally:
        engine.dispose()

(It's possible that engine.dispose() still needs to be run, so please check whether the if text: conditional should actually be inside the try block.)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least one of the examples (sqlite), requires multiple executing multiple text values, so this could possibly get a little messy. If we just had a context manager provide an engine that is always disposed, would that resolve your concern? Then we could also clean up duplicate code between create_database and drop_database.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I addressed that by putting both commands into the same line. I don't anticipate it being messy, but could be wrong.

elif dialect_name == 'sqlite' and database != ':memory:':
    if database:
        text = 'CREATE TABLE DB(id int); DROP TABLE DB;'


elif dialect_name == 'mysql':
with engine.begin() as conn:
text = "CREATE DATABASE {} CHARACTER SET = '{}'".format(
quote(conn, database), encoding
)
conn.execute(sa.text(text))
with engine.begin() as conn:
text = "CREATE DATABASE {} ENCODING '{}' TEMPLATE {}".format(
quote(conn, database), encoding, quote(conn, template)
)
conn.execute(sa.text(text))

elif dialect_name == 'sqlite' and database != ':memory:':
if database:
elif dialect_name == 'mysql':
with engine.begin() as conn:
conn.execute(sa.text('CREATE TABLE DB(id int)'))
conn.execute(sa.text('DROP TABLE DB'))
text = "CREATE DATABASE {} CHARACTER SET = '{}'".format(
quote(conn, database), encoding
)
conn.execute(sa.text(text))

else:
with engine.begin() as conn:
text = f'CREATE DATABASE {quote(conn, database)}'
conn.execute(sa.text(text))
elif dialect_name == 'sqlite' and database != ':memory:':
if database:
with engine.begin() as conn:
conn.execute(sa.text('CREATE TABLE DB(id int)'))
conn.execute(sa.text('DROP TABLE DB'))

else:
with engine.begin() as conn:
text = f'CREATE DATABASE {quote(conn, database)}'
conn.execute(sa.text(text))

engine.dispose()
finally:
engine.dispose()


def drop_database(url):
Expand Down Expand Up @@ -631,12 +633,14 @@ def drop_database(url):
else:
engine = sa.create_engine(url)

if dialect_name == 'sqlite' and database != ':memory:':
if database:
os.remove(database)
else:
with engine.begin() as conn:
text = f'DROP DATABASE {quote(conn, database)}'
conn.execute(sa.text(text))
try:
if dialect_name == 'sqlite' and database != ':memory:':
if database:
os.remove(database)
else:
with engine.begin() as conn:
text = f'DROP DATABASE {quote(conn, database)}'
conn.execute(sa.text(text))

engine.dispose()
finally:
engine.dispose()