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

feat: Drop database #1092

Merged
merged 6 commits into from
Sep 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
8 changes: 8 additions & 0 deletions docs/source/reference/evaql/drop.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,11 @@ DROP FUNCTION
.. code:: mysql

DROP FUNCTION FastRCNNObjectDetector;

DROP DATABASE
-------------

.. code:: mysql

DROP DATABASE postgres_db;
DROP DATABASE IF EXISTS postgres_db;
4 changes: 1 addition & 3 deletions evadb/catalog/catalog_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,7 @@ def get_database_catalog_entry(self, database_name: str) -> DatabaseCatalogEntry

return table_entry

def delete_database_catalog_entry(
self, database_entry: DatabaseCatalogEntry
) -> bool:
def drop_database_catalog_entry(self, database_entry: DatabaseCatalogEntry) -> bool:
"""
This method deletes the database from catalog.

Expand Down
26 changes: 26 additions & 0 deletions evadb/executor/drop_object_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ def exec(self, *args, **kwargs):
elif self.node.object_type == ObjectType.FUNCTION:
yield self._handle_drop_function(self.node.name, self.node.if_exists)

elif self.node.object_type == ObjectType.DATABASE:
yield self._handle_drop_database(self.node.name, self.node.if_exists)

def _handle_drop_table(self, table_name: str, if_exists: bool):
if not self.catalog().check_table_exists(table_name):
err_msg = "Table: {} does not exist".format(table_name)
Expand Down Expand Up @@ -132,3 +135,26 @@ def _handle_drop_index(self, index_name: str, if_exists: bool):
index=[0],
)
)

def _handle_drop_database(self, database_name: str, if_exists: bool):
db_catalog_entry = self.catalog().get_database_catalog_entry(database_name)
if not db_catalog_entry:
err_msg = (
f"Database {database_name} does not exist, therefore cannot be dropped."
)
if if_exists:
logger.warning(err_msg)
return Batch(pd.DataFrame([err_msg]))
else:
raise RuntimeError(err_msg)

logger.debug(f"Dropping database {database_name}")

self.catalog().drop_database_catalog_entry(db_catalog_entry)

return Batch(
pd.DataFrame(
{f"Database {database_name} successfully dropped"},
index=[0],
)
)
14 changes: 14 additions & 0 deletions evadb/parser/lark_visitor/_drop_statement.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,17 @@ def drop_function(self, tree):
if_exists = True

return DropObjectStatement(ObjectType.FUNCTION, function_name, if_exists)

# Drop Database
def drop_database(self, tree):
database_name = None
if_exists = False

for child in tree.children:
if isinstance(child, Tree):
if child.data == "if_exists":
if_exists = True
elif child.data == "uid":
database_name = self.visit(child)

return DropObjectStatement(ObjectType.DATABASE, database_name, if_exists)
1 change: 1 addition & 0 deletions evadb/parser/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,4 @@ class ObjectType(EvaDBEnum):
TABLE # noqa: F821
FUNCTION # noqa: F821
INDEX # noqa: F821
DATABASE # noqa: F821
4 changes: 4 additions & 0 deletions evadb/parser/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ def parse_drop_index(index_name: str, if_exists: bool):
return parse_drop(ObjectType.INDEX, index_name, if_exists)


def parse_drop_database(database_name: str, if_exists: bool):
return parse_drop(ObjectType.DATABASE, database_name, if_exists)


def parse_query(query):
stmt = Parser().parse(query)
assert len(stmt) == 1
Expand Down
36 changes: 36 additions & 0 deletions test/integration_tests/short/test_drop_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,3 +191,39 @@ def test_should_drop_index(self):
self.assertTrue(index_obj is None)

# todo check if the index is also removed from the underlying vector store

#### DROP INDEX

def test_should_drop_database(self):
# Create database.
database_name = "test_data_source"
params = {
"database": "evadb.db",
}
query = f"""CREATE DATABASE {database_name}
WITH ENGINE = "sqlite",
PARAMETERS = {params};"""
execute_query_fetch_all(self.evadb, query)
self.assertIsNotNone(
self.evadb.catalog().get_database_catalog_entry(database_name)
)

# DROP DATABASE
execute_query_fetch_all(self.evadb, f"DROP DATABASE {database_name}")
self.assertIsNone(
self.evadb.catalog().get_database_catalog_entry(database_name)
)

# DROP should pass with warning
result = execute_query_fetch_all(
self.evadb, f"DROP DATABASE IF EXISTS {database_name}"
)
self.assertTrue("does not exist" in result.frames.to_string())

# DROP should throw error
with self.assertRaises(ExecutorError):
execute_query_fetch_all(
self.evadb,
f"DROP DATABASE {database_name}",
do_not_print_exceptions=True,
)