Skip to content

Commit 54d66af

Browse files
committed
bindings-macro: add custom index name to prevent index name collisions
1 parent e33cefb commit 54d66af

1 file changed

Lines changed: 10 additions & 40 deletions

File tree

crates/bindings-macro/src/table.rs

Lines changed: 10 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -260,44 +260,6 @@ impl IndexArg {
260260
check_duplicate_msg(&algo, &meta, "index algorithm specified twice")?;
261261
algo = Some(Self::parse_direct(meta)?);
262262
}
263-
sym::name => {
264-
// If the user is trying to specify a `name`, do a bit of guessing at what their goal is.
265-
// This is going to be best-effort, and we're not going to try to do lookahead or anything.
266-
267-
return Err(if accessor.is_some() {
268-
// If the user's already specified an `accessor`,
269-
// then probably they're trying to specify the canonical name,
270-
// like you can for tables.
271-
// Print an error that says this is unsupported.
272-
meta.error(
273-
"Unexpected argument `name` in index definition.
274-
275-
Overwriting the `name` of an index is currently unsupported.",
276-
)
277-
} else if let Ok(sym) = meta.value().and_then(|val| val.parse::<Ident>()) {
278-
// If we haven't seen an `accessor` yet, and the value is an ident,
279-
// then probably this is 1.* syntax that needs a migration.
280-
// Note that, if the user specifies `name = {ident}` followed by `accessor = {ident}`,
281-
// we'll hit this branch, even though the diagnostic doesn't apply and we'd prefer not to.
282-
// I (pgoldman 2026-02-18) don't see a good way to distinguish this case
283-
// without making our parsing dramatically more complicated,
284-
// and it seems unlikely to occur.
285-
meta.error(format_args!(
286-
"Expected an `accessor` in index definition, but got a `name` instead.
287-
288-
If you're migrating from SpacetimeDB 1.*, replace `name = {sym}` with `accessor = {sym}`."
289-
))
290-
} else {
291-
// If we haven't seen an `accessor` yet, but the value is not an ident,
292-
// then we're not really sure what's going wrong, so print a more generic error message.
293-
meta.error(format_args!(
294-
"Unexpected argument `name` in index definition.
295-
296-
Overwriting the `name` of an index is currently unsupported.
297-
Did you mean to specify an `accessor` instead? Do so with `accessor = my_index`, where `my_index` is an unquoted identifier."
298-
))
299-
});
300-
}
301263
});
302264
Ok(())
303265
})?;
@@ -369,6 +331,7 @@ Did you mean to specify an `accessor` instead? Do so with `accessor = my_index`,
369331
/// Parses an inline `#[index(btree)]`, `#[index(hash)]`, or `#[index(direct)]` attribute on a field.
370332
fn parse_index_attr(field: &Ident, attr: &syn::Attribute) -> syn::Result<Self> {
371333
let mut kind = None;
334+
let mut name = None;
372335
attr.parse_nested_meta(|meta| {
373336
match_meta!(match meta {
374337
sym::btree => {
@@ -387,6 +350,10 @@ Did you mean to specify an `accessor` instead? Do so with `accessor = my_index`,
387350
check_duplicate_msg(&kind, &meta, "index type specified twice")?;
388351
kind = Some(IndexType::Direct { column: field.clone() })
389352
}
353+
sym::name => {
354+
check_duplicate(&name, &meta)?;
355+
name = Some(meta.value()?.parse()?);
356+
}
390357
});
391358
Ok(())
392359
})?;
@@ -395,7 +362,7 @@ Did you mean to specify an `accessor` instead? Do so with `accessor = my_index`,
395362

396363
// Default accessor = field name if not provided
397364
let accessor = field.clone();
398-
Ok(IndexArg::new(accessor, kind, None))
365+
Ok(IndexArg::new(accessor, kind, name))
399366
}
400367

401368
fn validate<'a>(&'a self, table_name: &str, cols: &'a [Column<'a>]) -> syn::Result<ValidatedIndex<'a>> {
@@ -436,7 +403,10 @@ Did you mean to specify an `accessor` instead? Do so with `accessor = my_index`,
436403
is_unique: self.is_unique,
437404
// This must be the canonical name (name used internally in database),
438405
// as it is used in `index_id_from_name` abi.
439-
index_name: gen_index_name(),
406+
index_name: match self.canonical_name.as_ref() {
407+
Some(s) => s.value(),
408+
None => gen_index_name(),
409+
},
440410
accessor_name: &self.accessor,
441411
kind,
442412
canonical_name: self.canonical_name.as_ref().map(|s| s.value()),

0 commit comments

Comments
 (0)