Repository: mathesar-foundation/mathesar

Issue:
Typecating column to JSON_List/Map doesn't work.
## 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. -->

1. Create an empty table.
2. Create a new column and add a JSON array to it.
3.  Try to typecast the column to JSON List.
4. Notice there is no error/change to the data type of the column.


## Additional context
<!-- Add any other context about the problem or screenshots here. -->
![Screenshot from 2022-11-19 22-09-51](https://user-images.githubusercontent.com/52523023/202862061-f447aeb4-9af0-4054-b398-f3288ba50a5c.png)



Discussion:
This is happening for both our custom JSON List and Json Object Map. The reason the casting isn't working is that the front end isn't submitting the proper type name, prefixed with the `mathesar_types` namespace. See the difference with `mathesar_types.email` for an example. 

As for the back end, we should certainly be throwing an error when a request to change to a type we don't know is submitted, rather than failing silently.

Resolving patch:
diff --git a/mathesar/api/serializers/columns.py b/mathesar/api/serializers/columns.py
--- a/mathesar/api/serializers/columns.py
+++ b/mathesar/api/serializers/columns.py
@@ -1,4 +1,4 @@
-from rest_framework import serializers
+from rest_framework import serializers, status
 from rest_framework.exceptions import ValidationError
 from rest_framework.fields import empty, SerializerMethodField
 from rest_framework.settings import api_settings
@@ -8,6 +8,10 @@
     DisplayOptionsMappingSerializer,
     DISPLAY_OPTIONS_SERIALIZER_MAPPING_KEY,
 )
+from mathesar.api.exceptions.database_exceptions import (
+    exceptions as database_api_exceptions,
+)
+from db.columns.exceptions import InvalidTypeError
 from mathesar.models.base import Column
 from db.types.operations.convert import get_db_type_enum_from_id
 
@@ -147,15 +151,20 @@ class Meta(SimpleColumnSerializer.Meta):
     def validate(self, data):
         data = super().validate(data)
         # Reevaluate column display options based on the new column type.
-        if TYPE_KEY in data and DISPLAY_OPTIONS_KEY not in data:
-            if self.instance:
+        if TYPE_KEY in data and self.instance:
+            db_type = get_db_type_enum_from_id(data[TYPE_KEY].lower())
+            target_types = self.instance.valid_target_types
+            if db_type not in target_types:
+                raise database_api_exceptions.InvalidTypeCastAPIException(
+                    InvalidTypeError,
+                    status_code=status.HTTP_400_BAD_REQUEST
+                )
+            if DISPLAY_OPTIONS_KEY not in data:
                 db_type = getattr(self.instance, 'db_type', None)
                 # Invalidate display_options if type has been changed
                 if db_type is not None:
                     if str(db_type.id) != data[TYPE_KEY]:
                         data[DISPLAY_OPTIONS_KEY] = None
-            else:
-                data[DISPLAY_OPTIONS_KEY] = None
         if not self.partial:
             from_scratch_required_fields = [TYPE_KEY]
             from_scratch_specific_fields = [TYPE_KEY, 'nullable', 'primary_key']


Test patch:
diff --git a/mathesar/tests/api/test_column_api_display_options.py b/mathesar/tests/api/test_column_api_display_options.py
--- a/mathesar/tests/api/test_column_api_display_options.py
+++ b/mathesar/tests/api/test_column_api_display_options.py
@@ -303,7 +303,7 @@ def test_column_create_wrong_display_options(
 
 def test_column_update_display_options(column_test_table_with_service_layer_options, client):
     table, _ = column_test_table_with_service_layer_options
-    column_indexes = [2, 3, 4, 5]
+    column_indexes = [2, 3, 4]
     for column_index in column_indexes:
         colum_name = f"mycolumn{column_index}"
         column = table.get_columns_by_name([colum_name])[0]