Skip to content

Commit 1df6c4d

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

1 file changed

Lines changed: 12 additions & 43 deletions

File tree

crates/bindings-macro/src/table.rs

Lines changed: 12 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -243,11 +243,6 @@ impl IndexArg {
243243
check_duplicate(&accessor, &meta)?;
244244
accessor = Some(meta.value()?.parse()?);
245245
}
246-
sym::name => {
247-
check_duplicate(&canonical_name, &meta)?;
248-
canonical_name = Some(meta.value()?.parse()?);
249-
}
250-
251246
sym::btree => {
252247
check_duplicate_msg(&algo, &meta, "index algorithm specified twice")?;
253248
algo = Some(Self::parse_btree(meta)?);
@@ -261,42 +256,8 @@ impl IndexArg {
261256
algo = Some(Self::parse_direct(meta)?);
262257
}
263258
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-
});
259+
check_duplicate(&canonical_name, &meta)?;
260+
canonical_name = Some(meta.value()?.parse()?);
300261
}
301262
});
302263
Ok(())
@@ -369,6 +330,7 @@ Did you mean to specify an `accessor` instead? Do so with `accessor = my_index`,
369330
/// Parses an inline `#[index(btree)]`, `#[index(hash)]`, or `#[index(direct)]` attribute on a field.
370331
fn parse_index_attr(field: &Ident, attr: &syn::Attribute) -> syn::Result<Self> {
371332
let mut kind = None;
333+
let mut name = None;
372334
attr.parse_nested_meta(|meta| {
373335
match_meta!(match meta {
374336
sym::btree => {
@@ -387,6 +349,10 @@ Did you mean to specify an `accessor` instead? Do so with `accessor = my_index`,
387349
check_duplicate_msg(&kind, &meta, "index type specified twice")?;
388350
kind = Some(IndexType::Direct { column: field.clone() })
389351
}
352+
sym::name => {
353+
check_duplicate(&name, &meta)?;
354+
name = Some(meta.value()?.parse()?);
355+
}
390356
});
391357
Ok(())
392358
})?;
@@ -395,7 +361,7 @@ Did you mean to specify an `accessor` instead? Do so with `accessor = my_index`,
395361

396362
// Default accessor = field name if not provided
397363
let accessor = field.clone();
398-
Ok(IndexArg::new(accessor, kind, None))
364+
Ok(IndexArg::new(accessor, kind, name))
399365
}
400366

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

0 commit comments

Comments
 (0)