We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Function to handle deleting schemas
**Problem**
<!-- Please provide a clear and concise description of the problem that this feature request is designed to solve.-->
Users might want to delete schemas. We don't currently support this.

**Proposed solution**
<!-- A clear and concise description of your proposed solution or feature. -->
A function that handles deleting of schemas in the database. We should raise an error if there is anything outside of the schema referencing the schema.

**Additional context**
<!-- Add any other context or screenshots about the feature request here.-->
This should be in the `db` module.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `db/schemas.py`
Content:
```
1 import logging
2 import warnings
3 from sqlalchemy.schema import CreateSchema
4 from sqlalchemy import inspect, MetaData, select, and_, not_, or_, Table
5 
6 from db import types
7 
8 logger = logging.getLogger(__name__)
9 
10 TYPES_SCHEMA = types.base.SCHEMA
11 
12 EXCLUDED_SCHEMATA = [TYPES_SCHEMA, "information_schema"]
13 
14 
15 def get_schema_name_from_oid(oid, engine):
16     return reflect_schema(engine, oid=oid)["name"]
17 
18 
19 def get_schema_oid_from_name(name, engine):
20     return reflect_schema(engine, name=name)["oid"]
21 
22 
23 def reflect_schema(engine, name=None, oid=None):
24     # If we have both arguments, the behavior is undefined.
25     try:
26         assert name is None or oid is None
27     except AssertionError as e:
28         logger.error("ERROR:  Only one of 'name' or 'oid' can be given!")
29         raise e
30     metadata = MetaData()
31     with warnings.catch_warnings():
32         warnings.filterwarnings("ignore", message="Did not recognize type")
33         pg_namespace = Table("pg_namespace", metadata, autoload_with=engine)
34     sel = (
35         select(pg_namespace.c.oid, pg_namespace.c.nspname.label("name"))
36         .where(or_(pg_namespace.c.nspname == name, pg_namespace.c.oid == oid))
37     )
38     with engine.begin() as conn:
39         schema_info = conn.execute(sel).fetchone()
40     return schema_info
41 
42 
43 def get_mathesar_schemas(engine):
44     return [schema for schema, _ in get_mathesar_schemas_with_oids(engine)]
45 
46 
47 def get_mathesar_schemas_with_oids(engine):
48     metadata = MetaData()
49     with warnings.catch_warnings():
50         warnings.filterwarnings("ignore", message="Did not recognize type")
51         pg_namespace = Table("pg_namespace", metadata, autoload_with=engine)
52     sel = (
53         select(pg_namespace.c.nspname.label('schema'), pg_namespace.c.oid)
54         .where(
55             and_(
56                 *[pg_namespace.c.nspname != schema for schema in EXCLUDED_SCHEMATA],
57                 not_(pg_namespace.c.nspname.like("pg_%"))
58             )
59         )
60     )
61     with engine.begin() as conn:
62         result = conn.execute(sel).fetchall()
63     return result
64 
65 
66 def get_all_schemas(engine):
67     inspector = inspect(engine)
68     # We don't need to exclude system schemas (i.e., starting with "pg_")
69     # since Inspector.get_schema_names already excludes them.  Thus, this
70     # function actually gets all non-pg-reserved schemas.
71     return inspector.get_schema_names()
72 
73 
74 def create_schema(schema, engine):
75     """
76     This method creates a Postgres schema.
77     """
78     if schema not in get_all_schemas(engine):
79         with engine.begin() as connection:
80             connection.execute(CreateSchema(schema))
81
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/db/schemas.py b/db/schemas.py
--- a/db/schemas.py
+++ b/db/schemas.py
@@ -1,7 +1,11 @@
 import logging
 import warnings
-from sqlalchemy.schema import CreateSchema
+from sqlalchemy.schema import CreateSchema, DropSchema
 from sqlalchemy import inspect, MetaData, select, and_, not_, or_, Table
+from sqlalchemy.exc import InternalError
+from sqlalchemy.schema import DDLElement
+from sqlalchemy.ext import compiler
+from psycopg2.errors import DependentObjectsStillExist
 
 from db import types
 
@@ -78,3 +82,42 @@
     if schema not in get_all_schemas(engine):
         with engine.begin() as connection:
             connection.execute(CreateSchema(schema))
+
+
+def delete_schema(schema, engine, cascade=False, if_exists=False):
+    """
+    This method deletes a Postgres schema.
+    """
+    if if_exists and schema not in get_all_schemas(engine):
+        return
+
+    with engine.begin() as connection:
+        try:
+            connection.execute(DropSchema(schema, cascade=cascade))
+        except InternalError as e:
+            if isinstance(e.orig, DependentObjectsStillExist):
+                raise e.orig
+            else:
+                raise e
+
+
+class RenameSchema(DDLElement):
+    def __init__(self, schema, rename_to):
+        self.schema = schema
+        self.rename_to = rename_to
+
+
+@compiler.compiles(RenameSchema)
+def compile_rename_schema(element, compiler, **_):
+    return "ALTER SCHEMA %s RENAME TO %s" % (
+        element.schema,
+        element.rename_to
+    )
+
+
+def rename_schema(schema, engine, rename_to):
+    """
+    This method renames a Postgres schema.
+    """
+    with engine.begin() as connection:
+        connection.execute(RenameSchema(schema, rename_to))

{"golden_diff": "diff --git a/db/schemas.py b/db/schemas.py\n--- a/db/schemas.py\n+++ b/db/schemas.py\n@@ -1,7 +1,11 @@\n import logging\n import warnings\n-from sqlalchemy.schema import CreateSchema\n+from sqlalchemy.schema import CreateSchema, DropSchema\n from sqlalchemy import inspect, MetaData, select, and_, not_, or_, Table\n+from sqlalchemy.exc import InternalError\n+from sqlalchemy.schema import DDLElement\n+from sqlalchemy.ext import compiler\n+from psycopg2.errors import DependentObjectsStillExist\n \n from db import types\n \n@@ -78,3 +82,42 @@\n     if schema not in get_all_schemas(engine):\n         with engine.begin() as connection:\n             connection.execute(CreateSchema(schema))\n+\n+\n+def delete_schema(schema, engine, cascade=False, if_exists=False):\n+    \"\"\"\n+    This method deletes a Postgres schema.\n+    \"\"\"\n+    if if_exists and schema not in get_all_schemas(engine):\n+        return\n+\n+    with engine.begin() as connection:\n+        try:\n+            connection.execute(DropSchema(schema, cascade=cascade))\n+        except InternalError as e:\n+            if isinstance(e.orig, DependentObjectsStillExist):\n+                raise e.orig\n+            else:\n+                raise e\n+\n+\n+class RenameSchema(DDLElement):\n+    def __init__(self, schema, rename_to):\n+        self.schema = schema\n+        self.rename_to = rename_to\n+\n+\n+@compiler.compiles(RenameSchema)\n+def compile_rename_schema(element, compiler, **_):\n+    return \"ALTER SCHEMA %s RENAME TO %s\" % (\n+        element.schema,\n+        element.rename_to\n+    )\n+\n+\n+def rename_schema(schema, engine, rename_to):\n+    \"\"\"\n+    This method renames a Postgres schema.\n+    \"\"\"\n+    with engine.begin() as connection:\n+        connection.execute(RenameSchema(schema, rename_to))\n", "issue": "Function to handle deleting schemas\n**Problem**\r\n<!-- Please provide a clear and concise description of the problem that this feature request is designed to solve.-->\r\nUsers might want to delete schemas. We don't currently support this.\r\n\r\n**Proposed solution**\r\n<!-- A clear and concise description of your proposed solution or feature. -->\r\nA function that handles deleting of schemas in the database. We should raise an error if there is anything outside of the schema referencing the schema.\r\n\r\n**Additional context**\r\n<!-- Add any other context or screenshots about the feature request here.-->\r\nThis should be in the `db` module.\n", "before_files": [{"content": "import logging\nimport warnings\nfrom sqlalchemy.schema import CreateSchema\nfrom sqlalchemy import inspect, MetaData, select, and_, not_, or_, Table\n\nfrom db import types\n\nlogger = logging.getLogger(__name__)\n\nTYPES_SCHEMA = types.base.SCHEMA\n\nEXCLUDED_SCHEMATA = [TYPES_SCHEMA, \"information_schema\"]\n\n\ndef get_schema_name_from_oid(oid, engine):\n    return reflect_schema(engine, oid=oid)[\"name\"]\n\n\ndef get_schema_oid_from_name(name, engine):\n    return reflect_schema(engine, name=name)[\"oid\"]\n\n\ndef reflect_schema(engine, name=None, oid=None):\n    # If we have both arguments, the behavior is undefined.\n    try:\n        assert name is None or oid is None\n    except AssertionError as e:\n        logger.error(\"ERROR:  Only one of 'name' or 'oid' can be given!\")\n        raise e\n    metadata = MetaData()\n    with warnings.catch_warnings():\n        warnings.filterwarnings(\"ignore\", message=\"Did not recognize type\")\n        pg_namespace = Table(\"pg_namespace\", metadata, autoload_with=engine)\n    sel = (\n        select(pg_namespace.c.oid, pg_namespace.c.nspname.label(\"name\"))\n        .where(or_(pg_namespace.c.nspname == name, pg_namespace.c.oid == oid))\n    )\n    with engine.begin() as conn:\n        schema_info = conn.execute(sel).fetchone()\n    return schema_info\n\n\ndef get_mathesar_schemas(engine):\n    return [schema for schema, _ in get_mathesar_schemas_with_oids(engine)]\n\n\ndef get_mathesar_schemas_with_oids(engine):\n    metadata = MetaData()\n    with warnings.catch_warnings():\n        warnings.filterwarnings(\"ignore\", message=\"Did not recognize type\")\n        pg_namespace = Table(\"pg_namespace\", metadata, autoload_with=engine)\n    sel = (\n        select(pg_namespace.c.nspname.label('schema'), pg_namespace.c.oid)\n        .where(\n            and_(\n                *[pg_namespace.c.nspname != schema for schema in EXCLUDED_SCHEMATA],\n                not_(pg_namespace.c.nspname.like(\"pg_%\"))\n            )\n        )\n    )\n    with engine.begin() as conn:\n        result = conn.execute(sel).fetchall()\n    return result\n\n\ndef get_all_schemas(engine):\n    inspector = inspect(engine)\n    # We don't need to exclude system schemas (i.e., starting with \"pg_\")\n    # since Inspector.get_schema_names already excludes them.  Thus, this\n    # function actually gets all non-pg-reserved schemas.\n    return inspector.get_schema_names()\n\n\ndef create_schema(schema, engine):\n    \"\"\"\n    This method creates a Postgres schema.\n    \"\"\"\n    if schema not in get_all_schemas(engine):\n        with engine.begin() as connection:\n            connection.execute(CreateSchema(schema))\n", "path": "db/schemas.py"}], "after_files": [{"content": "import logging\nimport warnings\nfrom sqlalchemy.schema import CreateSchema, DropSchema\nfrom sqlalchemy import inspect, MetaData, select, and_, not_, or_, Table\nfrom sqlalchemy.exc import InternalError\nfrom sqlalchemy.schema import DDLElement\nfrom sqlalchemy.ext import compiler\nfrom psycopg2.errors import DependentObjectsStillExist\n\nfrom db import types\n\nlogger = logging.getLogger(__name__)\n\nTYPES_SCHEMA = types.base.SCHEMA\n\nEXCLUDED_SCHEMATA = [TYPES_SCHEMA, \"information_schema\"]\n\n\ndef get_schema_name_from_oid(oid, engine):\n    return reflect_schema(engine, oid=oid)[\"name\"]\n\n\ndef get_schema_oid_from_name(name, engine):\n    return reflect_schema(engine, name=name)[\"oid\"]\n\n\ndef reflect_schema(engine, name=None, oid=None):\n    # If we have both arguments, the behavior is undefined.\n    try:\n        assert name is None or oid is None\n    except AssertionError as e:\n        logger.error(\"ERROR:  Only one of 'name' or 'oid' can be given!\")\n        raise e\n    metadata = MetaData()\n    with warnings.catch_warnings():\n        warnings.filterwarnings(\"ignore\", message=\"Did not recognize type\")\n        pg_namespace = Table(\"pg_namespace\", metadata, autoload_with=engine)\n    sel = (\n        select(pg_namespace.c.oid, pg_namespace.c.nspname.label(\"name\"))\n        .where(or_(pg_namespace.c.nspname == name, pg_namespace.c.oid == oid))\n    )\n    with engine.begin() as conn:\n        schema_info = conn.execute(sel).fetchone()\n    return schema_info\n\n\ndef get_mathesar_schemas(engine):\n    return [schema for schema, _ in get_mathesar_schemas_with_oids(engine)]\n\n\ndef get_mathesar_schemas_with_oids(engine):\n    metadata = MetaData()\n    with warnings.catch_warnings():\n        warnings.filterwarnings(\"ignore\", message=\"Did not recognize type\")\n        pg_namespace = Table(\"pg_namespace\", metadata, autoload_with=engine)\n    sel = (\n        select(pg_namespace.c.nspname.label('schema'), pg_namespace.c.oid)\n        .where(\n            and_(\n                *[pg_namespace.c.nspname != schema for schema in EXCLUDED_SCHEMATA],\n                not_(pg_namespace.c.nspname.like(\"pg_%\"))\n            )\n        )\n    )\n    with engine.begin() as conn:\n        result = conn.execute(sel).fetchall()\n    return result\n\n\ndef get_all_schemas(engine):\n    inspector = inspect(engine)\n    # We don't need to exclude system schemas (i.e., starting with \"pg_\")\n    # since Inspector.get_schema_names already excludes them.  Thus, this\n    # function actually gets all non-pg-reserved schemas.\n    return inspector.get_schema_names()\n\n\ndef create_schema(schema, engine):\n    \"\"\"\n    This method creates a Postgres schema.\n    \"\"\"\n    if schema not in get_all_schemas(engine):\n        with engine.begin() as connection:\n            connection.execute(CreateSchema(schema))\n\n\ndef delete_schema(schema, engine, cascade=False, if_exists=False):\n    \"\"\"\n    This method deletes a Postgres schema.\n    \"\"\"\n    if if_exists and schema not in get_all_schemas(engine):\n        return\n\n    with engine.begin() as connection:\n        try:\n            connection.execute(DropSchema(schema, cascade=cascade))\n        except InternalError as e:\n            if isinstance(e.orig, DependentObjectsStillExist):\n                raise e.orig\n            else:\n                raise e\n\n\nclass RenameSchema(DDLElement):\n    def __init__(self, schema, rename_to):\n        self.schema = schema\n        self.rename_to = rename_to\n\n\n@compiler.compiles(RenameSchema)\ndef compile_rename_schema(element, compiler, **_):\n    return \"ALTER SCHEMA %s RENAME TO %s\" % (\n        element.schema,\n        element.rename_to\n    )\n\n\ndef rename_schema(schema, engine, rename_to):\n    \"\"\"\n    This method renames a Postgres schema.\n    \"\"\"\n    with engine.begin() as connection:\n        connection.execute(RenameSchema(schema, rename_to))\n", "path": "db/schemas.py"}]}