@@ -128,6 +128,9 @@ pub fn schema_updates(
128
128
if let Some ( known_schema) = known_tables. remove ( proposed_table_name) {
129
129
let known_schema_def = TableDef :: from ( known_schema. as_ref ( ) . clone ( ) ) ;
130
130
if !equiv ( & known_schema_def, & proposed_schema_def) {
131
+ log:: warn!( "Schema incompatible: {proposed_table_name}" ) ;
132
+ log:: debug!( "Existing: {known_schema_def:?}" ) ;
133
+ log:: debug!( "Proposed: {proposed_schema_def:?}" ) ;
131
134
tainted_tables. push ( Tainted {
132
135
table_name : proposed_table_name. to_owned ( ) ,
133
136
reason : TaintReason :: IncompatibleSchema ,
@@ -167,11 +170,30 @@ pub fn schema_updates(
167
170
///
168
171
/// - `indexes` are never equal, because they only exist in the database
169
172
/// - `sequences` are never equal, because they only exist in the database
170
- /// - only `constraints` which have set column attributes can be equal (the
171
- /// module may emit unset attributes)
173
+ /// - `constraints` are delicate:
172
174
///
173
- /// Thus, `indexes` and `sequences` are ignored, while `constraints` are
174
- /// compared sans any unset attributes.
175
+ /// - The number of `constraints` obtained from the module will always be the
176
+ /// same as the number of columns, emitting [`Constraints::unset()`] if no
177
+ /// specific constraint is defined.
178
+ ///
179
+ /// - Indexes defined using `#[spacetimedb(index, ..)]` will not have a
180
+ /// corresponding [`Constraints::indexed()`] constraint (it will be unset).
181
+ /// The schema obtained from the database **will** have one such constraint,
182
+ /// however.
183
+ ///
184
+ /// - The other possibilities (primary key, autoinc, unique) will have a
185
+ /// [`ConstraintDef`] in the module's schema, but no corresponding index
186
+ /// or sequence definitions.
187
+ ///
188
+ /// There is no stable API to migrate such changes, so we won't try.
189
+ ///
190
+ /// Thus:
191
+ ///
192
+ /// - `indexes` and `sequences` are ignored
193
+ /// - `constraints` are compared sans unset or indexed-only definitions
194
+ ///
195
+ /// A return value of `false` indicates that the table definitions are not
196
+ /// compatible.
175
197
fn equiv ( a : & TableDef , b : & TableDef ) -> bool {
176
198
let TableDef {
177
199
table_name,
@@ -188,7 +210,11 @@ fn equiv(a: &TableDef, b: &TableDef) -> bool {
188
210
fn as_set ( constraints : & [ ConstraintDef ] ) -> BTreeSet < & ConstraintDef > {
189
211
constraints
190
212
. iter ( )
191
- . filter ( |c| c. constraints != Constraints :: unset ( ) )
213
+ . filter ( |c| {
214
+ ![ Constraints :: unset ( ) , Constraints :: indexed ( ) ]
215
+ . iter ( )
216
+ . any ( |val| val == & c. constraints )
217
+ } )
192
218
. collect ( )
193
219
}
194
220
0 commit comments