Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[db-queries] Decouples CTE usage from Diesel (RegionAllocation) #5063

Merged
merged 16 commits into from
Mar 27, 2024
Merged
23 changes: 22 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ cfg-if = "1.0"
chrono = { version = "0.4", features = [ "serde" ] }
clap = { version = "4.5", features = ["cargo", "derive", "env", "wrap_help"] }
colored = "2.1"
const_format = "0.2.32"
cookie = "0.18"
criterion = { version = "0.5.1", features = [ "async_tokio" ] }
crossbeam = "0.8"
Expand Down
1 change: 0 additions & 1 deletion nexus/db-model/src/queries/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@

//! Subqueries used in CTEs.

pub mod region_allocation;
pub mod virtual_provisioning_collection_update;
195 changes: 0 additions & 195 deletions nexus/db-model/src/queries/region_allocation.rs

This file was deleted.

1 change: 1 addition & 0 deletions nexus/db-queries/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ base64.workspace = true
bb8.workspace = true
camino.workspace = true
chrono.workspace = true
const_format.workspace = true
cookie.workspace = true
diesel.workspace = true
diesel-dtrace.workspace = true
Expand Down
62 changes: 0 additions & 62 deletions nexus/db-queries/src/db/cast_uuid_as_bytea.rs

This file was deleted.

27 changes: 26 additions & 1 deletion nexus/db-queries/src/db/column_walker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

//! CTE utility for iterating over all columns in a table.

use crate::db::raw_query_builder::TrustedStr;
use diesel::prelude::*;
use std::marker::PhantomData;

Expand All @@ -17,14 +18,30 @@ pub(crate) struct ColumnWalker<T> {
remaining: PhantomData<T>,
}

pub type AllColumnsOf<T> = ColumnWalker<<T as diesel::Table>::AllColumns>;

impl<T> ColumnWalker<T> {
pub fn new() -> Self {
pub const fn new() -> Self {
Self { remaining: PhantomData }
}
}

macro_rules! impl_column_walker {
( $len:literal $($column:ident)+ ) => (
#[allow(dead_code)]
impl<$($column: Column),+> ColumnWalker<($($column,)+)> {
pub fn with_prefix(prefix: &'static str) -> TrustedStr {
// This string is derived from:
// - The "table" type, with associated columns, which
// are not controlled by an arbitrary user, and
// - The "prefix" type, which is a "&'static str" (AKA,
// hopefully known at compile-time, and not leaked).
TrustedStr::i_take_responsibility_for_validating_this_string(
[$([prefix, $column::NAME].join("."),)+].join(", ")
)
}
}

impl<$($column: Column),+> IntoIterator for ColumnWalker<($($column,)+)> {
type Item = &'static str;
type IntoIter = std::array::IntoIter<Self::Item, $len>;
Expand Down Expand Up @@ -109,4 +126,12 @@ mod test {
assert_eq!(iter.next(), Some("value"));
assert_eq!(iter.next(), None);
}

#[test]
fn test_all_columns_with_prefix() {
assert_eq!(
AllColumnsOf::<test_table::table>::with_prefix("foo").as_str(),
"foo.id, foo.value, foo.time_deleted"
);
}
}
11 changes: 11 additions & 0 deletions nexus/db-queries/src/db/datastore/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -949,10 +949,21 @@ mod test {
assert_eq!(expected_region_count, dataset_and_regions.len());
let mut disk_datasets = HashSet::new();
let mut disk_zpools = HashSet::new();
let mut regions = HashSet::new();

for (dataset, region) in dataset_and_regions {
// Must be 3 unique datasets
assert!(disk_datasets.insert(dataset.id()));
// All regions should be unique
assert!(regions.insert(region.id()));

// Check there's no cross contamination between returned UUIDs
//
// This is a little goofy, but it catches a bug that has
// happened before. The returned columns share names (like
// "id"), so we need to process them in-order.
assert!(regions.get(&dataset.id()).is_none());
assert!(disk_datasets.get(&region.id()).is_none());

// Dataset must not be eligible for provisioning.
if let Some(kind) =
Expand Down
Loading
Loading