Repository: mathesar-foundation/mathesar

Issue:
Table records GET: Count mismatch when filter is applied
## Description
GET on table records, returns 'count' in response. Without any filters, the count reflects the total number of records. Currently, when we have a filter, the count still reflects the total number.

## Expected behavior
When a filter is applied, the count should reflect the number of filtered records.


Discussion:

Resolving patch:
diff --git a/db/tables.py b/db/tables.py
--- a/db/tables.py
+++ b/db/tables.py
@@ -6,6 +6,7 @@
 )
 from sqlalchemy.schema import DDLElement
 from sqlalchemy.ext import compiler
+from sqlalchemy_filters import apply_filters
 
 from db import columns, constants, schemas
 from db.types import inference
@@ -390,8 +391,10 @@ def create_empty_table(name):
     return Table(name, MetaData())
 
 
-def get_count(table, engine):
+def get_count(table, engine, filters=[]):
     query = select([func.count()]).select_from(table)
+    if filters is not None:
+        query = apply_filters(query, filters)
     with engine.begin() as conn:
         return conn.execute(query).scalar()
 
diff --git a/mathesar/models.py b/mathesar/models.py
--- a/mathesar/models.py
+++ b/mathesar/models.py
@@ -118,14 +118,13 @@ def drop_column(self, column_index):
             column_index,
         )
 
-    @property
-    def sa_num_records(self):
-        return tables.get_count(self._sa_table, self.schema._sa_engine)
-
     @property
     def sa_all_records(self):
         return records.get_records(self._sa_table, self.schema._sa_engine)
 
+    def sa_num_records(self, filters=[]):
+        return tables.get_count(self._sa_table, self.schema._sa_engine, filters=filters)
+
     def get_record(self, id_value):
         return records.get_record(self._sa_table, self.schema._sa_engine, id_value)
 
diff --git a/mathesar/pagination.py b/mathesar/pagination.py
--- a/mathesar/pagination.py
+++ b/mathesar/pagination.py
@@ -38,7 +38,7 @@ def paginate_queryset(self, queryset, request, table_id,
         self.offset = self.get_offset(request)
         # TODO: Cache count value somewhere, since calculating it is expensive.
         table = queryset.get(id=table_id)
-        self.count = table.sa_num_records
+        self.count = table.sa_num_records(filters=filters)
         self.request = request
 
         return table.get_records(


Test patch:
diff --git a/mathesar/tests/imports/test_csv.py b/mathesar/tests/imports/test_csv.py
--- a/mathesar/tests/imports/test_csv.py
+++ b/mathesar/tests/imports/test_csv.py
@@ -17,7 +17,7 @@ def test_csv_upload_with_all_required_parameters(engine, csv_filename, test_db_n
         assert table.name == 'NASA'
         assert table.schema.name == 'Patents'
         assert table.schema.database == test_db_name
-        assert table.sa_num_records == 1393
+        assert table.sa_num_records() == 1393
 
 
 def test_csv_upload_with_parameters_positional(engine, csv_filename, test_db_name):
@@ -32,7 +32,7 @@ def test_csv_upload_with_parameters_positional(engine, csv_filename, test_db_nam
         assert table.name == 'NASA 2'
         assert table.schema.name == 'Patents'
         assert table.schema.database == test_db_name
-        assert table.sa_num_records == 1393
+        assert table.sa_num_records() == 1393
 
 
 def test_csv_upload_with_duplicate_table_name(engine, csv_filename, test_db_name):
@@ -53,7 +53,7 @@ def test_csv_upload_with_duplicate_table_name(engine, csv_filename, test_db_name
         assert table.name == table_name
         assert table.schema.name == schema_name
         assert table.schema.database == test_db_name
-        assert table.sa_num_records == 1393
+        assert table.sa_num_records() == 1393
     with open(csv_filename, 'rb') as csv_file:
         with pytest.raises(InvalidRequestError) as excinfo:
             legacy_create_table_from_csv(
diff --git a/mathesar/tests/views/api/test_record_api.py b/mathesar/tests/views/api/test_record_api.py
--- a/mathesar/tests/views/api/test_record_api.py
+++ b/mathesar/tests/views/api/test_record_api.py
@@ -82,9 +82,8 @@ def test_record_list_filter(create_table, client):
         response_data = response.json()
 
     assert response.status_code == 200
-    assert response_data['count'] == 1393
+    assert response_data['count'] == 2
     assert len(response_data['results']) == 2
-    print(response_data['results'])
 
     assert mock_infer.call_args is not None
     assert mock_infer.call_args[1]['filters'] == filter_list