We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
IndexError when trying to load Mathesar without any tables
## Description
<!-- A clear and concise description of what the bug is. -->
Mathesar's UI does not load if there are no tables in the UI. There's an error with an index being out of range.

## Expected behavior
<!-- A clear and concise description of what you expected to happen. -->
Mathesar's UI should load.

## To Reproduce
<!-- How can we recreate this bug? Please try to provide a Minimal, Complete, and Verifiable (http://stackoverflow.com/help/mcve) example if code-related. -->
Ensure you have no tables in your connected DB and try to load the Mathesar homepage.

## Additional context
<!-- Add any other context about the problem or screenshots here. -->

Traceback:

```
Environment:


Request Method: GET
Request URL: http://localhost:8000/mathesar_tables

Django Version: 3.1.7
Python Version: 3.9.6
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'rest_framework',
 'django_filters',
 'django_property_filter',
 'mathesar']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/code/mathesar/views/frontend.py", line 42, in index
    "schemas": get_schemas(request),
  File "/code/mathesar/views/frontend.py", line 17, in get_schemas
    return schema_serializer.data
  File "/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py", line 745, in data
    ret = super().data
  File "/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py", line 246, in data
    self._data = self.to_representation(self.instance)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py", line 663, in to_representation
    return [
  File "/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py", line 664, in <listcomp>
    self.child.to_representation(item) for item in iterable
  File "/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py", line 515, in to_representation
    ret[field.field_name] = field.to_representation(attribute)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py", line 663, in to_representation
    return [
  File "/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py", line 664, in <listcomp>
    self.child.to_representation(item) for item in iterable
  File "/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py", line 502, in to_representation
    attribute = field.get_attribute(instance)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/fields.py", line 457, in get_attribute
    return get_attribute(instance, self.source_attrs)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/fields.py", line 97, in get_attribute
    instance = getattr(instance, attr)
  File "/usr/local/lib/python3.9/site-packages/django/utils/functional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/code/mathesar/models.py", line 89, in name
    return self._sa_table.name
  File "/usr/local/lib/python3.9/site-packages/django/utils/functional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/code/mathesar/models.py", line 75, in _sa_table
    table = tables.reflect_table_from_oid(
  File "/code/db/tables.py", line 358, in reflect_table_from_oid
    schema, table_name = conn.execute(sel).fetchall()[0]

Exception Type: IndexError at /mathesar_tables
Exception Value: list index out of range
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mathesar/models.py`
Content:
```
1 from django.contrib.auth.models import User
2 from django.core.cache import cache
3 from django.db import models
4 from django.utils.functional import cached_property
5 
6 from mathesar.database.base import create_mathesar_engine
7 from mathesar.utils import models as model_utils
8 from db import tables, records, schemas, columns
9 
10 NAME_CACHE_INTERVAL = 60 * 5
11 
12 
13 class BaseModel(models.Model):
14     created_at = models.DateTimeField(auto_now_add=True)
15     updated_at = models.DateTimeField(auto_now=True)
16 
17     class Meta:
18         abstract = True
19 
20 
21 class DatabaseObject(BaseModel):
22     oid = models.IntegerField()
23 
24     class Meta:
25         abstract = True
26 
27     def __str__(self):
28         return f"{self.__class__.__name__}: {self.oid}"
29 
30 
31 # TODO: Replace with a proper form of caching
32 # See: https://github.com/centerofci/mathesar/issues/280
33 _engines = {}
34 
35 
36 class Schema(DatabaseObject):
37     database = models.CharField(max_length=128)
38 
39     @property
40     def _sa_engine(self):
41         global _engines
42         # We're caching this since the engine is used frequently.
43         if self.database not in _engines:
44             _engines[self.database] = create_mathesar_engine(self.database)
45         return _engines[self.database]
46 
47     @cached_property
48     def name(self):
49         cache_key = f"{self.database}_schema_name_{self.oid}"
50         try:
51             schema_name = cache.get(cache_key)
52             if schema_name is None:
53                 schema_name = schemas.get_schema_name_from_oid(
54                     self.oid, self._sa_engine
55                 )
56                 cache.set(cache_key, schema_name, NAME_CACHE_INTERVAL)
57             return schema_name
58         # We catch this error, since it lets us decouple the cadence of
59         # overall DB reflection from the cadence of cache expiration for
60         # schema names.  Also, it makes it obvious when the DB layer has
61         # been altered, as opposed to other reasons for a 404 when
62         # requesting a schema.
63         except TypeError:
64             return 'MISSING'
65 
66 
67 class Table(DatabaseObject):
68     schema = models.ForeignKey('Schema', on_delete=models.CASCADE,
69                                related_name='tables')
70     import_verified = models.BooleanField(blank=True, null=True)
71 
72     @cached_property
73     def _sa_table(self):
74         try:
75             table = tables.reflect_table_from_oid(
76                 self.oid, self.schema._sa_engine,
77             )
78         # We catch this error, since it lets us decouple the cadence of
79         # overall DB reflection from the cadence of cache expiration for
80         # table names.  Also, it makes it obvious when the DB layer has
81         # been altered, as opposed to other reasons for a 404 when
82         # requesting a table.
83         except TypeError:
84             table = tables.create_empty_table("MISSING")
85         return table
86 
87     @cached_property
88     def name(self):
89         return self._sa_table.name
90 
91     @property
92     def sa_columns(self):
93         return self._sa_table.columns
94 
95     @property
96     def sa_column_names(self):
97         return self.sa_columns.keys()
98 
99     def add_column(self, column_data):
100         return columns.create_column(
101             self.schema._sa_engine,
102             self.oid,
103             column_data,
104         )
105 
106     def alter_column(self, column_index, column_data):
107         return columns.alter_column(
108             self.schema._sa_engine,
109             self.oid,
110             column_index,
111             column_data,
112         )
113 
114     def drop_column(self, column_index):
115         columns.drop_column(
116             self.schema._sa_engine,
117             self.oid,
118             column_index,
119         )
120 
121     @property
122     def sa_all_records(self):
123         return records.get_records(self._sa_table, self.schema._sa_engine)
124 
125     def sa_num_records(self, filters=[]):
126         return tables.get_count(self._sa_table, self.schema._sa_engine, filters=filters)
127 
128     def get_record(self, id_value):
129         return records.get_record(self._sa_table, self.schema._sa_engine, id_value)
130 
131     def get_records(self, limit=None, offset=None, filters=[], order_by=[]):
132         return records.get_records(self._sa_table, self.schema._sa_engine, limit,
133                                    offset, filters=filters, order_by=order_by)
134 
135     def get_group_counts(
136         self, group_by, limit=None, offset=None, filters=[], order_by=[]
137     ):
138         return records.get_group_counts(self._sa_table, self.schema._sa_engine,
139                                         group_by, limit, offset, filters=filters,
140                                         order_by=order_by)
141 
142     def create_record_or_records(self, record_data):
143         return records.create_record_or_records(self._sa_table, self.schema._sa_engine, record_data)
144 
145     def update_record(self, id_value, record_data):
146         return records.update_record(self._sa_table, self.schema._sa_engine, id_value, record_data)
147 
148     def delete_record(self, id_value):
149         return records.delete_record(self._sa_table, self.schema._sa_engine, id_value)
150 
151 
152 class DataFile(BaseModel):
153     file = models.FileField(
154         upload_to=model_utils.user_directory_path,
155     )
156     user = models.ForeignKey(User, blank=True, null=True, on_delete=models.CASCADE)
157     table_imported_to = models.ForeignKey(Table, related_name="data_files", blank=True,
158                                           null=True, on_delete=models.SET_NULL)
159     delimiter = models.CharField(max_length=1, default=',', blank=True)
160     escapechar = models.CharField(max_length=1, blank=True)
161     quotechar = models.CharField(max_length=1, default='"', blank=True)
162
```
--- 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/mathesar/models.py b/mathesar/models.py
--- a/mathesar/models.py
+++ b/mathesar/models.py
@@ -75,12 +75,12 @@
             table = tables.reflect_table_from_oid(
                 self.oid, self.schema._sa_engine,
             )
-        # We catch this error, since it lets us decouple the cadence of
+        # We catch these errors, since it lets us decouple the cadence of
         # overall DB reflection from the cadence of cache expiration for
         # table names.  Also, it makes it obvious when the DB layer has
         # been altered, as opposed to other reasons for a 404 when
         # requesting a table.
-        except TypeError:
+        except (TypeError, IndexError):
             table = tables.create_empty_table("MISSING")
         return table

{"golden_diff": "diff --git a/mathesar/models.py b/mathesar/models.py\n--- a/mathesar/models.py\n+++ b/mathesar/models.py\n@@ -75,12 +75,12 @@\n             table = tables.reflect_table_from_oid(\n                 self.oid, self.schema._sa_engine,\n             )\n-        # We catch this error, since it lets us decouple the cadence of\n+        # We catch these errors, since it lets us decouple the cadence of\n         # overall DB reflection from the cadence of cache expiration for\n         # table names.  Also, it makes it obvious when the DB layer has\n         # been altered, as opposed to other reasons for a 404 when\n         # requesting a table.\n-        except TypeError:\n+        except (TypeError, IndexError):\n             table = tables.create_empty_table(\"MISSING\")\n         return table\n", "issue": "IndexError when trying to load Mathesar without any tables\n## Description\r\n<!-- A clear and concise description of what the bug is. -->\r\nMathesar's UI does not load if there are no tables in the UI. There's an error with an index being out of range.\r\n\r\n## Expected behavior\r\n<!-- A clear and concise description of what you expected to happen. -->\r\nMathesar's UI should load.\r\n\r\n## To Reproduce\r\n<!-- How can we recreate this bug? Please try to provide a Minimal, Complete, and Verifiable (http://stackoverflow.com/help/mcve) example if code-related. -->\r\nEnsure you have no tables in your connected DB and try to load the Mathesar homepage.\r\n\r\n## Additional context\r\n<!-- Add any other context about the problem or screenshots here. -->\r\n\r\nTraceback:\r\n\r\n```\r\nEnvironment:\r\n\r\n\r\nRequest Method: GET\r\nRequest URL: http://localhost:8000/mathesar_tables\r\n\r\nDjango Version: 3.1.7\r\nPython Version: 3.9.6\r\nInstalled Applications:\r\n['django.contrib.admin',\r\n 'django.contrib.auth',\r\n 'django.contrib.contenttypes',\r\n 'django.contrib.sessions',\r\n 'django.contrib.messages',\r\n 'django.contrib.staticfiles',\r\n 'rest_framework',\r\n 'django_filters',\r\n 'django_property_filter',\r\n 'mathesar']\r\nInstalled Middleware:\r\n['django.middleware.security.SecurityMiddleware',\r\n 'django.contrib.sessions.middleware.SessionMiddleware',\r\n 'django.middleware.common.CommonMiddleware',\r\n 'django.middleware.csrf.CsrfViewMiddleware',\r\n 'django.contrib.auth.middleware.AuthenticationMiddleware',\r\n 'django.contrib.messages.middleware.MessageMiddleware',\r\n 'django.middleware.clickjacking.XFrameOptionsMiddleware']\r\n\r\n\r\n\r\nTraceback (most recent call last):\r\n  File \"/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py\", line 47, in inner\r\n    response = get_response(request)\r\n  File \"/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py\", line 181, in _get_response\r\n    response = wrapped_callback(request, *callback_args, **callback_kwargs)\r\n  File \"/code/mathesar/views/frontend.py\", line 42, in index\r\n    \"schemas\": get_schemas(request),\r\n  File \"/code/mathesar/views/frontend.py\", line 17, in get_schemas\r\n    return schema_serializer.data\r\n  File \"/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py\", line 745, in data\r\n    ret = super().data\r\n  File \"/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py\", line 246, in data\r\n    self._data = self.to_representation(self.instance)\r\n  File \"/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py\", line 663, in to_representation\r\n    return [\r\n  File \"/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py\", line 664, in <listcomp>\r\n    self.child.to_representation(item) for item in iterable\r\n  File \"/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py\", line 515, in to_representation\r\n    ret[field.field_name] = field.to_representation(attribute)\r\n  File \"/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py\", line 663, in to_representation\r\n    return [\r\n  File \"/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py\", line 664, in <listcomp>\r\n    self.child.to_representation(item) for item in iterable\r\n  File \"/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py\", line 502, in to_representation\r\n    attribute = field.get_attribute(instance)\r\n  File \"/usr/local/lib/python3.9/site-packages/rest_framework/fields.py\", line 457, in get_attribute\r\n    return get_attribute(instance, self.source_attrs)\r\n  File \"/usr/local/lib/python3.9/site-packages/rest_framework/fields.py\", line 97, in get_attribute\r\n    instance = getattr(instance, attr)\r\n  File \"/usr/local/lib/python3.9/site-packages/django/utils/functional.py\", line 48, in __get__\r\n    res = instance.__dict__[self.name] = self.func(instance)\r\n  File \"/code/mathesar/models.py\", line 89, in name\r\n    return self._sa_table.name\r\n  File \"/usr/local/lib/python3.9/site-packages/django/utils/functional.py\", line 48, in __get__\r\n    res = instance.__dict__[self.name] = self.func(instance)\r\n  File \"/code/mathesar/models.py\", line 75, in _sa_table\r\n    table = tables.reflect_table_from_oid(\r\n  File \"/code/db/tables.py\", line 358, in reflect_table_from_oid\r\n    schema, table_name = conn.execute(sel).fetchall()[0]\r\n\r\nException Type: IndexError at /mathesar_tables\r\nException Value: list index out of range\r\n```\n", "before_files": [{"content": "from django.contrib.auth.models import User\nfrom django.core.cache import cache\nfrom django.db import models\nfrom django.utils.functional import cached_property\n\nfrom mathesar.database.base import create_mathesar_engine\nfrom mathesar.utils import models as model_utils\nfrom db import tables, records, schemas, columns\n\nNAME_CACHE_INTERVAL = 60 * 5\n\n\nclass BaseModel(models.Model):\n    created_at = models.DateTimeField(auto_now_add=True)\n    updated_at = models.DateTimeField(auto_now=True)\n\n    class Meta:\n        abstract = True\n\n\nclass DatabaseObject(BaseModel):\n    oid = models.IntegerField()\n\n    class Meta:\n        abstract = True\n\n    def __str__(self):\n        return f\"{self.__class__.__name__}: {self.oid}\"\n\n\n# TODO: Replace with a proper form of caching\n# See: https://github.com/centerofci/mathesar/issues/280\n_engines = {}\n\n\nclass Schema(DatabaseObject):\n    database = models.CharField(max_length=128)\n\n    @property\n    def _sa_engine(self):\n        global _engines\n        # We're caching this since the engine is used frequently.\n        if self.database not in _engines:\n            _engines[self.database] = create_mathesar_engine(self.database)\n        return _engines[self.database]\n\n    @cached_property\n    def name(self):\n        cache_key = f\"{self.database}_schema_name_{self.oid}\"\n        try:\n            schema_name = cache.get(cache_key)\n            if schema_name is None:\n                schema_name = schemas.get_schema_name_from_oid(\n                    self.oid, self._sa_engine\n                )\n                cache.set(cache_key, schema_name, NAME_CACHE_INTERVAL)\n            return schema_name\n        # We catch this error, since it lets us decouple the cadence of\n        # overall DB reflection from the cadence of cache expiration for\n        # schema names.  Also, it makes it obvious when the DB layer has\n        # been altered, as opposed to other reasons for a 404 when\n        # requesting a schema.\n        except TypeError:\n            return 'MISSING'\n\n\nclass Table(DatabaseObject):\n    schema = models.ForeignKey('Schema', on_delete=models.CASCADE,\n                               related_name='tables')\n    import_verified = models.BooleanField(blank=True, null=True)\n\n    @cached_property\n    def _sa_table(self):\n        try:\n            table = tables.reflect_table_from_oid(\n                self.oid, self.schema._sa_engine,\n            )\n        # We catch this error, since it lets us decouple the cadence of\n        # overall DB reflection from the cadence of cache expiration for\n        # table names.  Also, it makes it obvious when the DB layer has\n        # been altered, as opposed to other reasons for a 404 when\n        # requesting a table.\n        except TypeError:\n            table = tables.create_empty_table(\"MISSING\")\n        return table\n\n    @cached_property\n    def name(self):\n        return self._sa_table.name\n\n    @property\n    def sa_columns(self):\n        return self._sa_table.columns\n\n    @property\n    def sa_column_names(self):\n        return self.sa_columns.keys()\n\n    def add_column(self, column_data):\n        return columns.create_column(\n            self.schema._sa_engine,\n            self.oid,\n            column_data,\n        )\n\n    def alter_column(self, column_index, column_data):\n        return columns.alter_column(\n            self.schema._sa_engine,\n            self.oid,\n            column_index,\n            column_data,\n        )\n\n    def drop_column(self, column_index):\n        columns.drop_column(\n            self.schema._sa_engine,\n            self.oid,\n            column_index,\n        )\n\n    @property\n    def sa_all_records(self):\n        return records.get_records(self._sa_table, self.schema._sa_engine)\n\n    def sa_num_records(self, filters=[]):\n        return tables.get_count(self._sa_table, self.schema._sa_engine, filters=filters)\n\n    def get_record(self, id_value):\n        return records.get_record(self._sa_table, self.schema._sa_engine, id_value)\n\n    def get_records(self, limit=None, offset=None, filters=[], order_by=[]):\n        return records.get_records(self._sa_table, self.schema._sa_engine, limit,\n                                   offset, filters=filters, order_by=order_by)\n\n    def get_group_counts(\n        self, group_by, limit=None, offset=None, filters=[], order_by=[]\n    ):\n        return records.get_group_counts(self._sa_table, self.schema._sa_engine,\n                                        group_by, limit, offset, filters=filters,\n                                        order_by=order_by)\n\n    def create_record_or_records(self, record_data):\n        return records.create_record_or_records(self._sa_table, self.schema._sa_engine, record_data)\n\n    def update_record(self, id_value, record_data):\n        return records.update_record(self._sa_table, self.schema._sa_engine, id_value, record_data)\n\n    def delete_record(self, id_value):\n        return records.delete_record(self._sa_table, self.schema._sa_engine, id_value)\n\n\nclass DataFile(BaseModel):\n    file = models.FileField(\n        upload_to=model_utils.user_directory_path,\n    )\n    user = models.ForeignKey(User, blank=True, null=True, on_delete=models.CASCADE)\n    table_imported_to = models.ForeignKey(Table, related_name=\"data_files\", blank=True,\n                                          null=True, on_delete=models.SET_NULL)\n    delimiter = models.CharField(max_length=1, default=',', blank=True)\n    escapechar = models.CharField(max_length=1, blank=True)\n    quotechar = models.CharField(max_length=1, default='\"', blank=True)\n", "path": "mathesar/models.py"}], "after_files": [{"content": "from django.contrib.auth.models import User\nfrom django.core.cache import cache\nfrom django.db import models\nfrom django.utils.functional import cached_property\n\nfrom mathesar.database.base import create_mathesar_engine\nfrom mathesar.utils import models as model_utils\nfrom db import tables, records, schemas, columns\n\nNAME_CACHE_INTERVAL = 60 * 5\n\n\nclass BaseModel(models.Model):\n    created_at = models.DateTimeField(auto_now_add=True)\n    updated_at = models.DateTimeField(auto_now=True)\n\n    class Meta:\n        abstract = True\n\n\nclass DatabaseObject(BaseModel):\n    oid = models.IntegerField()\n\n    class Meta:\n        abstract = True\n\n    def __str__(self):\n        return f\"{self.__class__.__name__}: {self.oid}\"\n\n\n# TODO: Replace with a proper form of caching\n# See: https://github.com/centerofci/mathesar/issues/280\n_engines = {}\n\n\nclass Schema(DatabaseObject):\n    database = models.CharField(max_length=128)\n\n    @property\n    def _sa_engine(self):\n        global _engines\n        # We're caching this since the engine is used frequently.\n        if self.database not in _engines:\n            _engines[self.database] = create_mathesar_engine(self.database)\n        return _engines[self.database]\n\n    @cached_property\n    def name(self):\n        cache_key = f\"{self.database}_schema_name_{self.oid}\"\n        try:\n            schema_name = cache.get(cache_key)\n            if schema_name is None:\n                schema_name = schemas.get_schema_name_from_oid(\n                    self.oid, self._sa_engine\n                )\n                cache.set(cache_key, schema_name, NAME_CACHE_INTERVAL)\n            return schema_name\n        # We catch this error, since it lets us decouple the cadence of\n        # overall DB reflection from the cadence of cache expiration for\n        # schema names.  Also, it makes it obvious when the DB layer has\n        # been altered, as opposed to other reasons for a 404 when\n        # requesting a schema.\n        except TypeError:\n            return 'MISSING'\n\n\nclass Table(DatabaseObject):\n    schema = models.ForeignKey('Schema', on_delete=models.CASCADE,\n                               related_name='tables')\n    import_verified = models.BooleanField(blank=True, null=True)\n\n    @cached_property\n    def _sa_table(self):\n        try:\n            table = tables.reflect_table_from_oid(\n                self.oid, self.schema._sa_engine,\n            )\n        # We catch these errors, since it lets us decouple the cadence of\n        # overall DB reflection from the cadence of cache expiration for\n        # table names.  Also, it makes it obvious when the DB layer has\n        # been altered, as opposed to other reasons for a 404 when\n        # requesting a table.\n        except (TypeError, IndexError):\n            table = tables.create_empty_table(\"MISSING\")\n        return table\n\n    @cached_property\n    def name(self):\n        return self._sa_table.name\n\n    @property\n    def sa_columns(self):\n        return self._sa_table.columns\n\n    @property\n    def sa_column_names(self):\n        return self.sa_columns.keys()\n\n    def add_column(self, column_data):\n        return columns.create_column(\n            self.schema._sa_engine,\n            self.oid,\n            column_data,\n        )\n\n    def alter_column(self, column_index, column_data):\n        return columns.alter_column(\n            self.schema._sa_engine,\n            self.oid,\n            column_index,\n            column_data,\n        )\n\n    def drop_column(self, column_index):\n        columns.drop_column(\n            self.schema._sa_engine,\n            self.oid,\n            column_index,\n        )\n\n    @property\n    def sa_all_records(self):\n        return records.get_records(self._sa_table, self.schema._sa_engine)\n\n    def sa_num_records(self, filters=[]):\n        return tables.get_count(self._sa_table, self.schema._sa_engine, filters=filters)\n\n    def get_record(self, id_value):\n        return records.get_record(self._sa_table, self.schema._sa_engine, id_value)\n\n    def get_records(self, limit=None, offset=None, filters=[], order_by=[]):\n        return records.get_records(self._sa_table, self.schema._sa_engine, limit,\n                                   offset, filters=filters, order_by=order_by)\n\n    def get_group_counts(\n        self, group_by, limit=None, offset=None, filters=[], order_by=[]\n    ):\n        return records.get_group_counts(self._sa_table, self.schema._sa_engine,\n                                        group_by, limit, offset, filters=filters,\n                                        order_by=order_by)\n\n    def create_record_or_records(self, record_data):\n        return records.create_record_or_records(self._sa_table, self.schema._sa_engine, record_data)\n\n    def update_record(self, id_value, record_data):\n        return records.update_record(self._sa_table, self.schema._sa_engine, id_value, record_data)\n\n    def delete_record(self, id_value):\n        return records.delete_record(self._sa_table, self.schema._sa_engine, id_value)\n\n\nclass DataFile(BaseModel):\n    file = models.FileField(\n        upload_to=model_utils.user_directory_path,\n    )\n    user = models.ForeignKey(User, blank=True, null=True, on_delete=models.CASCADE)\n    table_imported_to = models.ForeignKey(Table, related_name=\"data_files\", blank=True,\n                                          null=True, on_delete=models.SET_NULL)\n    delimiter = models.CharField(max_length=1, default=',', blank=True)\n    escapechar = models.CharField(max_length=1, blank=True)\n    quotechar = models.CharField(max_length=1, default='\"', blank=True)\n", "path": "mathesar/models.py"}]}