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

Improve tables metadata #3672

Merged
merged 6 commits into from
Jul 11, 2024
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
6 changes: 3 additions & 3 deletions docs/docs/api/rpc.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ To use an RPC function:
options:
members:
- list_
- patch
- TableMetaData
- SettableTableMetaData
- set_
- TableMetaDataBlob
- TableMetaDataRecord

## Columns

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Generated by Django 4.2.11 on 2024-07-10 18:16

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('mathesar', '0009_add_column_metadata_model'),
]

operations = [
migrations.AlterField(
model_name='tablemetadata',
name='column_order',
field=models.JSONField(null=True),
),
migrations.AlterField(
model_name='tablemetadata',
name='import_verified',
field=models.BooleanField(null=True),
),
migrations.AlterField(
model_name='tablemetadata',
name='record_summary_customized',
field=models.BooleanField(null=True),
),
migrations.AlterField(
model_name='tablemetadata',
name='record_summary_template',
field=models.CharField(max_length=255, null=True),
),
]
8 changes: 4 additions & 4 deletions mathesar/models/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,10 @@ class Meta:
class TableMetaData(BaseModel):
database = models.ForeignKey('Database', on_delete=models.CASCADE)
table_oid = models.PositiveBigIntegerField()
import_verified = models.BooleanField(default=False)
column_order = models.JSONField(default=list)
record_summary_customized = models.BooleanField(default=False)
record_summary_template = models.CharField(max_length=255, blank=True)
import_verified = models.BooleanField(null=True)
column_order = models.JSONField(null=True)
record_summary_customized = models.BooleanField(null=True)
record_summary_template = models.CharField(max_length=255, null=True)

class Meta:
constraints = [
Expand Down
28 changes: 28 additions & 0 deletions mathesar/rpc/tables/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
from mathesar.rpc.columns import CreatableColumnInfo, SettableColumnInfo, PreviewableColumnInfo
from mathesar.rpc.constraints import CreatableConstraintInfo
from mathesar.rpc.exceptions.handlers import handle_rpc_exceptions
from mathesar.rpc.tables.metadata import TableMetaDataBlob
from mathesar.rpc.utils import connect
from mathesar.utils.tables import get_tables_meta_data


class TableInfo(TypedDict):
Expand Down Expand Up @@ -231,3 +233,29 @@ def get_import_preview(
user = kwargs.get(REQUEST_KEY).user
with connect(database_id, user) as conn:
return get_preview(table_oid, columns, conn, limit)


@rpc_method(name="tables.list_with_metadata")
@http_basic_auth_login_required
@handle_rpc_exceptions
def list_with_metadata(*, schema_oid: int, database_id: int, **kwargs) -> list:
"""
List tables in a schema, along with the metadata associated with each table

Args:
schema_oid: PostgreSQL OID of the schema containing the tables.
database_id: The Django id of the database containing the table.

Returns:
A list of table details.
"""
user = kwargs.get(REQUEST_KEY).user
with connect(database_id, user) as conn:
tables = get_table_info(schema_oid, conn)

metadata_records = get_tables_meta_data(database_id)
metadata_map = {
r.table_oid: TableMetaDataBlob.from_model(r) for r in metadata_records
}

return [table | {"metadata": metadata_map.get(table["oid"])} for table in tables]
41 changes: 23 additions & 18 deletions mathesar/rpc/tables/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
from modernrpc.auth.basic import http_basic_auth_login_required

from mathesar.rpc.exceptions.handlers import handle_rpc_exceptions
from mathesar.utils.tables import get_tables_meta_data, patch_table_meta_data
from mathesar.utils.tables import get_tables_meta_data, set_table_meta_data


class TableMetaData(TypedDict):
class TableMetaDataRecord(TypedDict):
"""
Metadata for a table in a database.

Expand Down Expand Up @@ -46,9 +46,9 @@ def from_model(cls, model):
)


class SettableTableMetaData(TypedDict):
class TableMetaDataBlob(TypedDict):
"""
Settable metadata fields for a table in a database.
The metadata fields which can be set on a table

Attributes:
import_verified: Specifies whether a file has been successfully imported into a table.
Expand All @@ -61,11 +61,20 @@ class SettableTableMetaData(TypedDict):
record_summary_customized: Optional[bool]
record_summary_template: Optional[str]

@classmethod
def from_model(cls, model):
return cls(
import_verified=model.import_verified,
column_order=model.column_order,
record_summary_customized=model.record_summary_customized,
record_summary_template=model.record_summary_template,
)


@rpc_method(name="tables.metadata.list")
@http_basic_auth_login_required
@handle_rpc_exceptions
def list_(*, database_id: int, **kwargs) -> list[TableMetaData]:
def list_(*, database_id: int, **kwargs) -> list[TableMetaDataRecord]:
"""
List metadata associated with tables for a database.

Expand All @@ -77,26 +86,22 @@ def list_(*, database_id: int, **kwargs) -> list[TableMetaData]:
"""
table_meta_data = get_tables_meta_data(database_id)
return [
TableMetaData.from_model(model) for model in table_meta_data
TableMetaDataRecord.from_model(model) for model in table_meta_data
]


@rpc_method(name="tables.metadata.patch")
@rpc_method(name="tables.metadata.set")
@http_basic_auth_login_required
@handle_rpc_exceptions
def patch(
*, table_oid: int, metadata_dict: SettableTableMetaData, database_id: int, **kwargs
) -> TableMetaData:
def set_(
*, table_oid: int, metadata: TableMetaDataBlob, database_id: int, **kwargs
) -> None:
"""
Alter metadata settings associated with a table for a database.
Set metadata for a table.

Args:
table_oid: Identity of the table whose metadata we'll modify.
metadata_dict: The dict describing desired table metadata alterations.
table_oid: The PostgreSQL OID of the table.
metadata: A TableMetaDataBlob object describing desired table metadata to set.
database_id: The Django id of the database containing the table.

Returns:
Altered metadata object.
"""
table_meta_data = patch_table_meta_data(table_oid, metadata_dict, database_id)
return TableMetaData.from_model(table_meta_data)
set_table_meta_data(table_oid, metadata, database_id)
27 changes: 2 additions & 25 deletions mathesar/tests/rpc/tables/test_t_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,39 +29,16 @@ def mock_get_tables_meta_data(_database_id):
monkeypatch.setattr(metadata, "get_tables_meta_data", mock_get_tables_meta_data)

expect_metadata_list = [
metadata.TableMetaData(
metadata.TableMetaDataRecord(
id=1, database_id=database_id, table_oid=1234,
import_verified=True, column_order=[8, 9, 10], record_summary_customized=False,
record_summary_template="{5555}"
),
metadata.TableMetaData(
metadata.TableMetaDataRecord(
id=2, database_id=database_id, table_oid=4567,
import_verified=False, column_order=[], record_summary_customized=True,
record_summary_template="{5512} {1223}"
)
]
actual_metadata_list = metadata.list_(database_id=database_id)
assert actual_metadata_list == expect_metadata_list


def test_tables_meta_data_patch(monkeypatch):
database_id = 2
metadata_dict = {'import_verified': True, 'column_order': [1, 4, 12]}

def mock_patch_tables_meta_data(table_oid, metadata_dict, _database_id):
server_model = Server(id=2, host='example.com', port=5432)
db_model = Database(id=_database_id, name='mymathesardb', server=server_model)
return TableMetaData(
id=1, database=db_model, table_oid=1234,
import_verified=True, column_order=[1, 4, 12], record_summary_customized=False,
record_summary_template="{5555}"
)
monkeypatch.setattr(metadata, "patch_table_meta_data", mock_patch_tables_meta_data)

expect_metadata_object = metadata.TableMetaData(
id=1, database_id=database_id, table_oid=1234,
import_verified=True, column_order=[1, 4, 12], record_summary_customized=False,
record_summary_template="{5555}"
)
actual_metadata_object = metadata.patch(table_oid=1234, metadata_dict=metadata_dict, database_id=2)
assert actual_metadata_object == expect_metadata_object
9 changes: 7 additions & 2 deletions mathesar/tests/rpc/test_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@
"tables.list",
[user_is_authenticated]
),
(
tables.list_with_metadata,
"tables.list_with_metadata",
[user_is_authenticated]
),
(
tables.get,
"tables.get",
Expand Down Expand Up @@ -142,8 +147,8 @@
[user_is_authenticated]
),
(
tables.metadata.patch,
"tables.metadata.patch",
tables.metadata.set_,
"tables.metadata.set",
[user_is_authenticated]
)
]
Expand Down
16 changes: 6 additions & 10 deletions mathesar/utils/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from mathesar.database.base import create_mathesar_engine
from mathesar.imports.base import create_table_from_data_file
from mathesar.models.deprecated import Table
from mathesar.models.base import TableMetaData
from mathesar.models.base import Database, TableMetaData
from mathesar.state.django import reflect_columns_from_tables
from mathesar.state import get_cached_metadata

Expand Down Expand Up @@ -90,13 +90,9 @@ def get_tables_meta_data(database_id):
return TableMetaData.objects.filter(database__id=database_id)


def patch_table_meta_data(table_oid, metadata_dict, database_id):
metadata_model = TableMetaData.objects.get(database__id=database_id, table_oid=table_oid)
alterable_fields = (
'import_verified', 'column_order', 'record_summary_customized', 'record_summary_template'
def set_table_meta_data(table_oid, metadata, database_id):
TableMetaData.objects.update_or_create(
database=Database.objects.get(id=database_id),
table_oid=table_oid,
defaults=metadata,
)
for field, value in metadata_dict.items():
if field in alterable_fields:
setattr(metadata_model, field, value)
metadata_model.save()
return metadata_model
Loading