Skip to content

Commit 73c2862

Browse files
committed
Finish index stuff
1 parent 39b19f7 commit 73c2862

File tree

1 file changed

+41
-51
lines changed
  • crates/bindings-macro/src

1 file changed

+41
-51
lines changed

crates/bindings-macro/src/lib.rs

Lines changed: 41 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use bitflags::Flags;
1515
use module::{derive_deserialize, derive_satstype, derive_serialize};
1616
use proc_macro::TokenStream as StdTokenStream;
1717
use proc_macro2::{Span, TokenStream};
18-
use quote::{format_ident, quote, quote_spanned, TokenStreamExt};
18+
use quote::{format_ident, quote, quote_spanned};
1919
use spacetimedb_primitives::ColumnAttribute;
2020
use std::collections::HashMap;
2121
use std::time::Duration;
@@ -433,23 +433,15 @@ fn reducer_type_check(item: &syn::DeriveInput, reducer_name: &Path) -> TokenStre
433433
}
434434

435435
struct IndexArg {
436-
name: Option<Ident>,
436+
#[allow(unused)]
437+
name: Ident,
437438
kind: IndexType,
438439
}
439440

440441
enum IndexType {
441442
BTree { columns: Vec<Ident> },
442443
}
443444

444-
impl quote::ToTokens for IndexType {
445-
fn to_tokens(&self, tokens: &mut TokenStream) {
446-
let kind = match self {
447-
IndexType::BTree { .. } => "BTree",
448-
};
449-
tokens.append(Ident::new(kind, Span::call_site()))
450-
}
451-
}
452-
453445
impl TableArgs {
454446
fn parse(input: TokenStream) -> syn::Result<Self> {
455447
let mut specified_access = false;
@@ -508,6 +500,7 @@ impl IndexArg {
508500
});
509501
Ok(())
510502
})?;
503+
let name = name.ok_or_else(|| meta.error("missing index name, e.g. name = my_index"))?;
511504
let kind = algo.ok_or_else(|| meta.error("missing index algorithm, e.g., `btree(columns = [col1, col2])`"))?;
512505

513506
Ok(IndexArg { name, kind })
@@ -536,7 +529,7 @@ impl IndexArg {
536529
Ok(IndexType::BTree { columns })
537530
}
538531

539-
/// Parses an inline `#[index(btree | hash)]` attribute on a field.
532+
/// Parses an inline `#[index(btree)]` attribute on a field.
540533
fn parse_index_attr(field: &Ident, attr: &syn::Attribute) -> syn::Result<Self> {
541534
let mut kind = None;
542535
attr.parse_nested_meta(|meta| {
@@ -551,22 +544,37 @@ impl IndexArg {
551544
Ok(())
552545
})?;
553546
let kind = kind.ok_or_else(|| syn::Error::new_spanned(&attr.meta, "must specify kind of index (`btree`)"))?;
554-
Ok(IndexArg { kind, name: None })
547+
let name = field.clone();
548+
Ok(IndexArg { kind, name })
555549
}
556550

557-
/// Returns the name the index will have
558-
/// assuming the table is named `table_name`
559-
/// and that the columns of the table are in `cols`.
560-
fn normalized_name(&self, table_name: &str, cols: &[&Column]) -> String {
561-
self.name
562-
.as_ref()
563-
.map(|s| s.to_string())
564-
.unwrap_or_else(|| match &self.kind {
565-
IndexType::BTree { .. } => (["btree", table_name].into_iter())
551+
fn to_index_desc(&self, table_name: &str, cols: &[Column]) -> Result<TokenStream, syn::Error> {
552+
match &self.kind {
553+
IndexType::BTree { columns } => {
554+
let cols = columns
555+
.iter()
556+
.map(|ident| {
557+
let col = cols
558+
.iter()
559+
.find(|col| col.field.ident == Some(ident))
560+
.ok_or_else(|| syn::Error::new(ident.span(), "not a column of the table"))?;
561+
Ok(col)
562+
})
563+
.collect::<syn::Result<Vec<_>>>()?;
564+
565+
let name = (["btree", table_name].into_iter())
566566
.chain(cols.iter().map(|col| col.field.name.as_deref().unwrap()))
567567
.collect::<Vec<_>>()
568-
.join("_"),
569-
})
568+
.join("_");
569+
570+
let col_ids = cols.iter().map(|col| col.index);
571+
Ok(quote!(spacetimedb::IndexDesc {
572+
name: #name,
573+
ty: spacetimedb::spacetimedb_lib::db::raw_def::IndexType::BTree,
574+
col_ids: &[#(#col_ids),*],
575+
}))
576+
}
577+
}
570578
}
571579
}
572580

@@ -601,13 +609,13 @@ impl IndexArg {
601609
/// system; `pub struct` or `pub(crate) struct` do not affect the table visibility, only
602610
/// the visibility of the items in your own source code.
603611
///
604-
/// * `index(name = "...", btree | hash = [a, b, c])`
612+
/// * `index(name = my_index, btree(columns = [a, b, c]))`
605613
///
606614
/// You can specify an index on 1 or more of the table's columns with the above syntax.
607-
/// You can also just put `#[index(btree | hash)]` on the field itself if you only need
615+
/// You can also just put `#[index(btree)]` on the field itself if you only need
608616
/// a single-column attribute; see column attributes below.
609617
///
610-
/// * `name = "..."`
618+
/// * `name = my_table`
611619
///
612620
/// Specify the name of the table in the database, if you want it to be different from
613621
/// the name of the struct.
@@ -633,7 +641,7 @@ impl IndexArg {
633641
///
634642
/// Similar to `#[unique]`, but generates additional CRUD methods.
635643
///
636-
/// * `#[index(btree | hash)]`
644+
/// * `#[index(btree)]`
637645
///
638646
/// Creates a single-column index with the specified algorithm.
639647
///
@@ -778,29 +786,11 @@ fn table_impl(mut args: TableArgs, mut item: MutItem<syn::DeriveInput>) -> syn::
778786
columns.push(column);
779787
}
780788

781-
let mut indexes = vec![];
782-
783-
for index in args.indices {
784-
let IndexType::BTree { columns: cols } = &index.kind;
785-
let cols = cols
786-
.iter()
787-
.map(|ident| {
788-
let col = columns
789-
.iter()
790-
.find(|col| col.field.ident == Some(ident))
791-
.ok_or_else(|| syn::Error::new(ident.span(), "not a column of the table"))?;
792-
Ok(col)
793-
})
794-
.collect::<syn::Result<Vec<_>>>()?;
795-
let name = index.normalized_name(&table_name, &cols);
796-
let col_ids = cols.iter().map(|col| col.index);
797-
let ty = &index.kind;
798-
indexes.push(quote!(spacetimedb::IndexDesc {
799-
name: #name,
800-
ty: spacetimedb::spacetimedb_lib::db::raw_def::IndexType::#ty,
801-
col_ids: &[#(#col_ids),*],
802-
}));
803-
}
789+
let indexes = args
790+
.indices
791+
.iter()
792+
.map(|index| index.to_index_desc(&table_name, &columns))
793+
.collect::<syn::Result<Vec<_>>>()?;
804794

805795
let (unique_columns, nonunique_columns): (Vec<_>, Vec<_>) =
806796
columns.iter().partition(|x| x.attr.contains(ColumnAttribute::UNIQUE));

0 commit comments

Comments
 (0)