Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions codegen/src/common/model/primary_key.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use indexmap::IndexMap;
use proc_macro2::{Ident, TokenStream};
use std::collections::HashMap;

#[derive(Debug, Clone)]
pub struct PrimaryKey {
pub ident: Ident,
pub values: HashMap<Ident, TokenStream>,
pub values: IndexMap<Ident, TokenStream>,
}

#[derive(Debug, Clone, Copy, PartialEq)]
Expand Down
4 changes: 2 additions & 2 deletions codegen/src/generators/in_memory/primary_key.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::HashMap;
use indexmap::IndexMap;

use crate::common::model::{GeneratorType, PrimaryKey};
use crate::common::name_generator::{WorktableNameGenerator, is_unsized_vec};
Expand Down Expand Up @@ -27,7 +27,7 @@ impl InMemoryGenerator {
.clone(),
)
})
.collect::<HashMap<_, _>>();
.collect::<IndexMap<_, _>>();

let def = self.gen_primary_key_type()?;
let impl_ = self.gen_table_primary_key_impl()?;
Expand Down
10 changes: 8 additions & 2 deletions codegen/src/generators/in_memory/queries/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,10 @@ impl InMemoryGenerator {
return Err(e);
}
};
let row = self.0.select(pk.clone()).unwrap();
let row = self.0
.data
.select_non_ghosted(link)
.map_err(WorkTableError::PagesError)?;
#process
}
} else {
Expand All @@ -129,7 +132,10 @@ impl InMemoryGenerator {
.get_value(&pk)
.map(Into::into)
.ok_or(WorkTableError::NotFound)?;
let row = self.0.select(pk.clone()).unwrap();
let row = self.0
.data
.select_non_ghosted(link)
.map_err(WorkTableError::PagesError)?;
#process
}
}
Expand Down
4 changes: 2 additions & 2 deletions codegen/src/generators/persist/primary_key.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::HashMap;
use indexmap::IndexMap;

use crate::common::model::{GeneratorType, PrimaryKey};
use crate::common::name_generator::{WorktableNameGenerator, is_unsized_vec};
Expand Down Expand Up @@ -26,7 +26,7 @@ impl PersistGenerator {
.clone(),
)
})
.collect::<HashMap<_, _>>();
.collect::<IndexMap<_, _>>();

let def = self.gen_primary_key_type()?;
let impl_ = self.gen_table_primary_key_impl()?;
Expand Down
10 changes: 8 additions & 2 deletions codegen/src/generators/persist/queries/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,10 @@ impl PersistGenerator {
return Err(e);
}
};
let row = self.0.select(pk.clone()).unwrap();
let row = self.0
.data
.select_non_ghosted(link)
.map_err(WorkTableError::PagesError)?;
#process
}
} else {
Expand All @@ -122,7 +125,10 @@ impl PersistGenerator {
.get_value(&pk)
.map(Into::into)
.ok_or(WorkTableError::NotFound)?;
let row = self.0.select(pk.clone()).unwrap();
let row = self.0
.data
.select_non_ghosted(link)
.map_err(WorkTableError::PagesError)?;
#process
}
}
Expand Down
4 changes: 2 additions & 2 deletions codegen/src/generators/read_only/primary_key.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::HashMap;
use indexmap::IndexMap;

use crate::common::model::{GeneratorType, PrimaryKey};
use crate::common::name_generator::{WorktableNameGenerator, is_unsized_vec};
Expand Down Expand Up @@ -26,7 +26,7 @@ impl ReadOnlyGenerator {
.clone(),
)
})
.collect::<HashMap<_, _>>();
.collect::<IndexMap<_, _>>();

let def = self.gen_primary_key_type()?;
let impl_ = self.gen_table_primary_key_impl()?;
Expand Down
34 changes: 34 additions & 0 deletions codegen/src/worktable/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,40 @@ mod tests {

use super::expand;

fn assert_composite_primary_key_field_order(output: proc_macro2::TokenStream) {
let output = output.to_string();
let get_primary_key = output
.split("fn get_primary_key")
.nth(1)
.expect("generated TableRow implementation");
let tenant = get_primary_key
.find("self . tenant_id . clone")
.expect("first primary-key field");
let record = get_primary_key
.find("self . record_id . clone")
.expect("second primary-key field");

assert!(tenant < record, "composite primary-key declaration order changed");
}

#[test]
fn composite_primary_key_codegen_preserves_declaration_order() {
for persist in [true, false] {
let output = expand(quote! {
name: CompositePrimaryKeyOrder,
persist: #persist,
columns: {
tenant_id: u64 primary_key,
record_id: u64 primary_key,
value: i64,
},
})
.unwrap();

assert_composite_primary_key_field_order(output);
}
}

#[test]
fn absent_using_keeps_worktables_index_default() {
let output = expand(quote! {
Expand Down
2 changes: 2 additions & 0 deletions tests/persistence/tuple_primary_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ async fn composite_primary_key_survives_mutations_and_reload() {
for row in &rows {
assert_eq!(table.select((row.tenant_id, row.record_id)), Some(row.clone()));
}
table.close().await.unwrap();
}

{
Expand Down Expand Up @@ -84,5 +85,6 @@ async fn composite_primary_key_survives_mutations_and_reload() {
assert!(table.select((7, 41)).is_none());
assert_eq!(table.select((7, 42)).unwrap().value, 99);
assert_eq!(table.select((8, 1)), Some(rows[2].clone()));
table.close().await.unwrap();
}
}
5 changes: 4 additions & 1 deletion tests/worktable/upsert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ async fn upsert_completes_under_same_key_churn() {
/// Intense variant for the same-key upsert/delete linearization protocol.
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn upsert_completes_under_extreme_same_key_churn() {
churn_run(5_000, 2_000).await;
// Keep this materially heavier than the normal case without making the
// assertion depend on runner speed: 2,000 churn flips perform both an
// upsert and a delete, alongside 4,000 competing upserts.
churn_run(2_000, 1_000).await;
}

/// A synchronous insert does not participate in the generated async row lock.
Expand Down
Loading