Skip to content

Commit 55805ef

Browse files
committed
added index name arg
1 parent 99897ab commit 55805ef

4 files changed

Lines changed: 56 additions & 20 deletions

File tree

crates/bindings-macro/src/table.rs

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use syn::parse::Parse;
1212
use syn::parse::Parser as _;
1313
use syn::punctuated::Punctuated;
1414
use syn::spanned::Spanned;
15+
use syn::LitStr;
1516
use syn::{parse_quote, Ident, Path, Token};
1617

1718
pub(crate) struct TableArgs {
@@ -46,19 +47,21 @@ struct ScheduledArg {
4647

4748
struct IndexArg {
4849
accessor: Ident,
50+
name: Option<LitStr>,
4951
is_unique: bool,
5052
kind: IndexType,
5153
}
5254

5355
impl IndexArg {
54-
fn new(accessor: Ident, kind: IndexType) -> Self {
56+
fn new(accessor: Ident, kind: IndexType, name: Option<LitStr>) -> Self {
5557
// We don't know if its unique yet.
5658
// We'll discover this once we have collected constraints.
5759
let is_unique = false;
5860
Self {
5961
accessor,
6062
is_unique,
6163
kind,
64+
name,
6265
}
6366
}
6467
}
@@ -157,6 +160,7 @@ impl ScheduledArg {
157160
impl IndexArg {
158161
fn parse_meta(meta: ParseNestedMeta) -> syn::Result<Self> {
159162
let mut accessor = None;
163+
let mut name = None;
160164
let mut algo = None;
161165

162166
meta.parse_nested_meta(|meta| {
@@ -165,6 +169,11 @@ impl IndexArg {
165169
check_duplicate(&accessor, &meta)?;
166170
accessor = Some(meta.value()?.parse()?);
167171
}
172+
sym::name => {
173+
check_duplicate(&name, &meta)?;
174+
let litstr: LitStr = meta.value()?.parse()?;
175+
name = Some(litstr);
176+
}
168177
sym::btree => {
169178
check_duplicate_msg(&algo, &meta, "index algorithm specified twice")?;
170179
algo = Some(Self::parse_btree(meta)?);
@@ -188,7 +197,7 @@ impl IndexArg {
188197
)
189198
})?;
190199

191-
Ok(IndexArg::new(accessor, kind))
200+
Ok(IndexArg::new(accessor, kind, name))
192201
}
193202

194203
fn parse_columns(meta: &ParseNestedMeta) -> syn::Result<Option<Vec<Ident>>> {
@@ -248,6 +257,8 @@ impl IndexArg {
248257
/// Parses an inline `#[index(btree)]`, `#[index(hash)]`, or `#[index(direct)]` attribute on a field.
249258
fn parse_index_attr(field: &Ident, attr: &syn::Attribute) -> syn::Result<Self> {
250259
let mut kind = None;
260+
let mut accessor: Option<Ident> = None;
261+
let mut name: Option<LitStr> = None;
251262
attr.parse_nested_meta(|meta| {
252263
match_meta!(match meta {
253264
sym::btree => {
@@ -266,13 +277,27 @@ impl IndexArg {
266277
check_duplicate_msg(&kind, &meta, "index type specified twice")?;
267278
kind = Some(IndexType::Direct { column: field.clone() })
268279
}
280+
sym::accessor => {
281+
check_duplicate(&accessor, &meta)?;
282+
accessor = Some(meta.value()?.parse()?);
283+
}
284+
sym::name => {
285+
check_duplicate(&name, &meta)?;
286+
name = Some(meta.value()?.parse()?);
287+
}
269288
});
270289
Ok(())
271290
})?;
272-
let kind = kind
273-
.ok_or_else(|| syn::Error::new_spanned(&attr.meta, "must specify kind of index (`btree` or `direct`)"))?;
274-
let name = field.clone();
275-
Ok(IndexArg::new(name, kind))
291+
let kind = kind.ok_or_else(|| {
292+
syn::Error::new_spanned(
293+
&attr.meta,
294+
"must specify kind of index (`btree` , `direct`, `name` or `value`)",
295+
)
296+
})?;
297+
298+
// Default accessor = field name if not provided
299+
let accessor = accessor.unwrap_or_else(|| field.clone());
300+
Ok(IndexArg::new(accessor, kind, name))
276301
}
277302

278303
fn validate<'a>(&'a self, table_name: &str, cols: &'a [Column<'a>]) -> syn::Result<ValidatedIndex<'a>> {
@@ -299,17 +324,19 @@ impl IndexArg {
299324
(ValidatedIndexType::Direct { col }, "direct")
300325
}
301326
};
302-
// See crates/schema/src/validate/v9.rs for the format of index names.
303-
// It's slightly unnerving that we just trust that component to generate this format correctly,
304-
// but what can you do.
305-
let cols = kind.columns();
306-
let cols = cols.iter().map(|col| col.ident.to_string()).collect::<Vec<_>>();
307-
let cols = cols.join("_");
308-
let index_name = format!("{table_name}_{cols}_idx_{kind_str}");
327+
let gen_index_name = || {
328+
// See crates/schema/src/validate/v9.rs for the format of index names.
329+
// It's slightly unnerving that we just trust that component to generate this format correctly,
330+
// but what can you do.
331+
let cols = kind.columns();
332+
let cols = cols.iter().map(|col| col.ident.to_string()).collect::<Vec<_>>();
333+
let cols = cols.join("_");
334+
format!("{table_name}_{cols}_idx_{kind_str}")
335+
};
309336

310337
Ok(ValidatedIndex {
311338
is_unique: self.is_unique,
312-
index_name,
339+
index_name: self.name.as_ref().map(|s| s.value()).unwrap_or_else(gen_index_name),
313340
accessor_name: &self.accessor,
314341
kind,
315342
})
@@ -417,10 +444,12 @@ impl ValidatedIndex<'_> {
417444
}
418445
};
419446
let accessor_name = ident_to_litstr(self.accessor_name);
447+
let index_name = &self.index_name;
420448
// Note: we do not pass the index_name through here.
421449
// We trust the schema validation logic to reconstruct the name we've stored in `self.name`.
422450
quote!(spacetimedb::table::IndexDesc {
423451
accessor_name: #accessor_name,
452+
index_name: #index_name,
424453
algo: #algo,
425454
})
426455
}
@@ -800,10 +829,11 @@ pub(crate) fn table_impl(mut args: TableArgs, item: &syn::DeriveInput) -> syn::R
800829
// NOTE(centril): We pick `btree` here if the user does not specify otherwise,
801830
// as it's the safest choice of index for the general case,
802831
// even if isn't optimal in specific cases.
803-
let name = unique_col.ident.clone();
804-
let columns = vec![name.clone()];
832+
let accessor = unique_col.ident.clone();
833+
let columns = vec![accessor.clone()];
805834
args.indices.push(IndexArg {
806-
accessor: name,
835+
accessor,
836+
name: None,
807837
is_unique: true,
808838
kind: IndexType::BTree { columns },
809839
})

crates/bindings/src/rt.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,7 @@ pub fn register_table<T: Table>() {
722722
table = table.with_unique_constraint(col);
723723
}
724724
for index in T::INDEXES {
725-
table = table.with_index(index.algo.into(), index.accessor_name);
725+
table = table.with_index(index.algo.into(), index.accessor_name, index.index_name);
726726
}
727727
if let Some(primary_key) = T::PRIMARY_KEY {
728728
table = table.with_primary_key(primary_key);

crates/bindings/src/table.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ pub trait TableInternal: Sized {
139139
#[derive(Clone, Copy)]
140140
pub struct IndexDesc<'a> {
141141
pub accessor_name: &'a str,
142+
pub index_name: &'a str,
142143
pub algo: IndexAlgo<'a>,
143144
}
144145

crates/lib/src/db/raw_def/v10.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,11 +1036,16 @@ impl RawTableDefBuilderV10<'_> {
10361036
}
10371037

10381038
/// Generates a [RawIndexDefV10] using the supplied `columns`.
1039-
pub fn with_index(mut self, algorithm: RawIndexAlgorithm, accessor_name: impl Into<RawIdentifier>) -> Self {
1039+
pub fn with_index(
1040+
mut self,
1041+
algorithm: RawIndexAlgorithm,
1042+
accessor_name: impl Into<RawIdentifier>,
1043+
index_name: impl Into<RawIdentifier>,
1044+
) -> Self {
10401045
let accessor_name = accessor_name.into();
10411046

10421047
self.table.indexes.push(RawIndexDefV10 {
1043-
source_name: None,
1048+
source_name: Some(index_name.into()),
10441049
accessor_name: Some(accessor_name),
10451050
algorithm,
10461051
});

0 commit comments

Comments
 (0)