Repository: edgedb/edgedb

Issue:
Can't create migration after changing pgvector length
<!-- Please search existing issues to avoid creating duplicates. -->

<!--
For the EdgeDB Version: run `edgedb query 'select sys::get_version_as_str()'` from your project directory (or run `select sys::get_version_as_str();` in the EdgeDB interactive shell).
For the EdgeDB CLI Version: Run `edgedb --version` from anywhere
-->

- EdgeDB Version: 4.5+28216a1
- EdgeDB CLI Version: 4.0.2+be1da73
- OS Version: GNU/Linux 6.7.3-arch1-1

```esdl
scalar type SearchEmbeddings extending ext::pgvector::vector<384>;
abstract type DealBase {
   embeddings: SearchEmbeddings;
}
```

create some DealBase with pgvector (attached example json with vector of 384 length)
[deal.json](https://github.com/edgedb/edgedb/files/14292723/deal.json)

Change pgvector length (e.g. to 768) and try to apply create migration. I'm getting following error:

```
edgedb error: EdgeDB could not resolve migration with the provided answers. Please retry with different answers.
```


Discussion:
We should produce a better failure than this, probably, but I think even if that is fixed it probably won't be possible to migrate directly like this.

You'll need to drop and recreate the `embeddings` field or you'll want to create a new search embeddings type, change the type in place (providing a conversion expression), and then drop the old type and rename

Resolving patch:
diff --git a/edb/schema/scalars.py b/edb/schema/scalars.py
--- a/edb/schema/scalars.py
+++ b/edb/schema/scalars.py
@@ -62,13 +62,13 @@ class ScalarType(
     )
 
     sql_type = so.SchemaField(
-        str, default=None, inheritable=False, compcoef=0.9)
+        str, default=None, inheritable=False, compcoef=0.0)
 
     # A type scheme for supporting type mods in scalar types.
     # If present, describes what the sql_type of children scalars
     # should be, such as 'varchar({__arg_0__})'.
     sql_type_scheme = so.SchemaField(
-        str, default=None, inheritable=False, compcoef=0.9)
+        str, default=None, inheritable=False, compcoef=0.0)
 
     # The number of parameters that the type takes. Currently all parameters
     # must be integer literals.
@@ -76,14 +76,16 @@ class ScalarType(
     num_params = so.SchemaField(
         int, default=None,
         inheritable=False,
-        compcoef=0.8,
+        compcoef=0.0,
     )
 
     # Arguments to fill in a parent type's parameterized type scheme.
     arg_values = so.SchemaField(
-        checked.FrozenCheckedList[str], default=None,
+        checked.FrozenCheckedList[str],
+        default=None,
         inheritable=False,
-        coerce=True, compcoef=0.8,
+        coerce=True,
+        compcoef=0.0,
     )
 
     @classmethod


Test patch:
diff --git a/tests/test_edgeql_data_migration.py b/tests/test_edgeql_data_migration.py
--- a/tests/test_edgeql_data_migration.py
+++ b/tests/test_edgeql_data_migration.py
@@ -3343,6 +3343,44 @@ async def test_edgeql_migration_reject_prop_05(self):
         ], check_complete=False)
         await self.fast_forward_describe_migration()
 
+    async def test_edgeql_migration_vector_change_01(self):
+        await self.migrate('''
+            using extension pgvector;
+            module default {
+                scalar type Embedding extending ext::pgvector::vector<384>;
+                type Obj {
+                   embeddings: Embedding;
+                }
+            }
+        ''', explicit_modules=True)
+
+        await self.start_migration('''
+            using extension pgvector;
+            module default {
+                scalar type Embedding extending ext::pgvector::vector<768>;
+                type Obj {
+                   embeddings: Embedding;
+                }
+            }
+        ''', explicit_modules=True)
+
+        await self.assert_describe_migration({
+            'proposed': {
+                'statements': [{
+                    'text': """
+                        ALTER TYPE default::Obj {DROP PROPERTY embeddings;};
+                    """
+                }]
+            }
+        })
+
+        # FIXME: Rejecting it still fails in a bad way.
+        # (This needs to fail in *some* way, but it ISEs.)
+        # await self.interact([
+        #     ("did you drop property 'embeddings' of object type "
+        #      "'default::Obj'?", "n"),
+        # ])
+
     async def test_edgeql_migration_force_delete_01(self):
         await self.migrate('''
             type Base;