-
-
Notifications
You must be signed in to change notification settings - Fork 53
Closed
Labels
enhancementNew feature or requestNew feature or request
Description
Summary
I would like to extend the database command to be able to do something like the following:
class DatabaseCLIPlugin(CLIPluginProtocol):
def on_cli_init(self, cli: Group) -> None:
db_group = get_alchemy_group()
@db_group.command(name="create-database", help="Uses the config connection_string to create a new database if none exists")
def create_database():
....
I can't seem to figure out a way to hook into the cli and extend the advanced alchemy command though. I can roll my db cli command and integrate that with litestar, but I'd rather not have two commands i.e. one called database
and then my custom one called db
.
Does anyone have any ideas?
Alternatively or additionally, is there any interest in taking up two new commands: create-db
and drop-db
which create and drop the database respectively. I tend to have these in a lot of my projects.
Thanks!
Basic Example
class CLIPlugin(CLIPluginProtocol):
def on_cli_init(self, cli: Group) -> None:
console = get_console()
# for create/drop commands we cannot be connected to the db we want to create/drop
app_db_url = urlparse(settings.DATABASE_URL)
app_db_name = app_db_url.path.replace("/", "")
pg_db_url_result = app_db_url._replace(path="/postgres")
pg_db_url = urlunparse(pg_db_url_result)
async_engine = create_async_engine(
url=pg_db_url,
execution_options={"isolation_level": "AUTOCOMMIT"},
)
@cli.command(name="db-create")
def create_database(app: Litestar) -> None:
async def _create_db():
async with async_engine.begin() as conn:
try:
sql = "CREATE DATABASE {} ENCODING '{}'".format(
app_db_name, "utf-8"
)
await conn.execute(text(sql))
except DatabaseError as err:
console.print(err)
asyncio.run(_create_db())
@cli.command(name="db-drop")
def drop_database(app: Litestar) -> None:
async def _drop_db():
async with async_engine.connect() as conn:
try:
conn = await conn.execution_options(
isolation_level="AUTOCOMMIT"
)
# We must first disconnect all users from the database we are dropping.
version = conn.dialect.server_version_info
pid_column = "pid" if (version >= (9, 2)) else "procpid"
drop_user_conn_sql = """SELECT pg_terminate_backend(pg_stat_activity.{pid_column})
FROM pg_stat_activity
WHERE pg_stat_activity.datname = '{database}'
AND {pid_column} <> pg_backend_pid();""".format(
pid_column=pid_column, database=app_db_name
)
await conn.execute(text(drop_user_conn_sql))
drop_sql = "DROP DATABASE {}".format(app_db_name)
await conn.execute(text(drop_sql))
console.print(f"dropped database '{app_db_name}'")
except DatabaseError as err:
console.print(f"Error dropping database: {err}")
except Exception as ex:
console.print(f"Unexpected error: {ex}")
await async_engine.dispose()
asyncio.run(_drop_db())
Drawbacks and Impact
No response
Unresolved questions
No response
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request