Skip to content
Merged
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
10 changes: 5 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ members = ["codegen", "examples", "performance_measurement", "performance_measur

[package]
name = "worktable"
version = "0.8.1"
version = "0.8.3"
edition = "2024"
authors = ["Handy-caT"]
license = "MIT"
Expand All @@ -27,14 +27,14 @@ lockfree = { version = "0.5.1" }
fastrand = "2.3.0"
futures = "0.3.30"
uuid = { version = "1.10.0", features = ["v4", "v7"] }
data_bucket = "0.3.1"
data_bucket = "0.3.2"
# data_bucket = { git = "https://github.com/pathscale/DataBucket", branch = "page_cdc_correction", version = "0.2.7" }
# data_bucket = { path = "../DataBucket", version = "0.3.0" }
# data_bucket = { path = "../DataBucket", version = "0.3.1" }
performance_measurement_codegen = { path = "performance_measurement/codegen", version = "0.1.0", optional = true }
performance_measurement = { path = "performance_measurement", version = "0.1.0", optional = true }
# indexset = { version = "0.12.3", features = ["concurrent", "cdc", "multimap"] }
# indexset = { package = "wt-indexset", path = "../indexset", version = "0.12.5", features = ["concurrent", "cdc", "multimap"] }
indexset = { package = "wt-indexset", version = "0.12.7", features = ["concurrent", "cdc", "multimap"] }
# indexset = { package = "wt-indexset", path = "../indexset", version = "0.12.8", features = ["concurrent", "cdc", "multimap"] }
indexset = { package = "wt-indexset", version = "0.12.8", features = ["concurrent", "cdc", "multimap"] }
convert_case = "0.6.0"
ordered-float = "5.0.0"
parking_lot = "0.12.3"
Expand Down
6 changes: 3 additions & 3 deletions codegen/src/worktable/generator/queries/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ impl Generator {
self.iter_with_async(|row| {
if row.#field == by {
futures::future::Either::Left(async move {
self.delete(row.id.into()).await
self.delete(row.get_primary_key()).await
})
} else {
futures::future::Either::Right(async {
Expand Down Expand Up @@ -180,7 +180,7 @@ impl Generator {
let rows_to_update = self.0.indexes.#index.get(#by).map(|kv| kv.1).collect::<Vec<_>>();
for link in rows_to_update {
let row = self.0.data.select_non_ghosted(*link).map_err(WorkTableError::PagesError)?;
self.delete(row.id.into()).await?;
self.delete(row.get_primary_key()).await?;
}
core::result::Result::Ok(())
}
Expand All @@ -202,7 +202,7 @@ impl Generator {
let row_to_update = self.0.indexes.#index.get(#by).map(|v| v.get().value);
if let Some(link) = row_to_update {
let row = self.0.data.select_non_ghosted(link).map_err(WorkTableError::PagesError)?;
self.delete(row.id.into()).await?;
self.delete(row.get_primary_key()).await?;
}
core::result::Result::Ok(())
}
Expand Down
4 changes: 4 additions & 0 deletions src/index/unsized_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ where
self.inner.last()
}

fn pre_max(&self) -> Option<&T> {
self.inner.pre_max()
}

fn min(&self) -> Option<&T> {
self.inner.first()
}
Expand Down
2 changes: 0 additions & 2 deletions src/persistence/space/index/unsized_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -401,14 +401,12 @@ where
let page_to_update = if let Some(page) = page {
page
} else {
// println!("Try to parse page: {:?} {:?}", page_index, page_id);
let page =
parse_page::<UnsizedIndexPage<T, INNER_PAGE_SIZE>, INNER_PAGE_SIZE>(
&mut self.index_file,
page_index.into(),
)
.await?;
// println!("Page {:?} {:?} parsed", page_index, page_id);
pages.insert(page_index, page);
pages
.get_mut(&page_index)
Expand Down
5 changes: 0 additions & 5 deletions src/table/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,6 @@ where
if let Some(link) = link {
self.data.select(link).ok()
} else {
println!(
"{:?} Unavailable in primary index, vals available {:?}",
pk,
self.pk_map.iter().collect::<Vec<_>>()
);
None
}
}
Expand Down
86 changes: 86 additions & 0 deletions tests/persistence/sync/many_strings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use worktable::prelude::*;
use worktable_codegen::worktable;

use crate::remove_dir_if_exists;

worktable! (
name: TestSync,
persist: true,
columns: {
id: String primary_key,
field: String,
another: u64,
},
queries: {
update: {
FieldAnotherById(field, another) by id,
},
}
);

#[test]
fn test_space_update_query_pk_sync() {
let config = PersistenceConfig::new(
"tests/data/unsized_primary_and_other_sync/update_query_pk",
"tests/data/unsized_primary_and_other_sync/update_query_pk",
);

let runtime = tokio::runtime::Builder::new_multi_thread()
.worker_threads(2)
.enable_io()
.enable_time()
.build()
.unwrap();

runtime.block_on(async {
remove_dir_if_exists(
"tests/data/unsized_primary_and_other_sync/update_query_pk".to_string(),
)
.await;

let pk = {
let table = TestSyncWorkTable::load_from_file(config.clone())
.await
.unwrap();
let row = TestSyncRow {
another: 42,
field: "".to_string(),
id: "Some string before".to_string(),
};
table.insert(row.clone()).unwrap();
let row = TestSyncRow {
another: 43,
field: "".to_string(),
id: "Some string before 2".to_string(),
};
table.insert(row.clone()).unwrap();
table.wait_for_ops().await;
row.id
};
{
let table = TestSyncWorkTable::load_from_file(config.clone())
.await
.unwrap();
assert!(table.select(pk.clone()).is_some());
assert_eq!(table.select(pk.clone()).unwrap().another, 43);
let q = FieldAnotherByIdQuery {
field: "Some field value".to_string(),
another: 0,
};
table
.update_field_another_by_id(q, pk.clone())
.await
.unwrap();
table.wait_for_ops().await;
}
{
let table = TestSyncWorkTable::load_from_file(config).await.unwrap();
assert!(table.select(pk.clone()).is_some());
assert_eq!(table.select(pk.clone()).unwrap().another, 0);
assert_eq!(
table.select(pk).unwrap().field,
"Some field value".to_string()
);
}
});
}
1 change: 1 addition & 0 deletions tests/persistence/sync/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::time::Duration;
use worktable::prelude::*;
use worktable::worktable;

mod many_strings;
mod string_primary_index;
mod string_re_read;
mod string_secondary_index;
Expand Down
23 changes: 23 additions & 0 deletions tests/worktable/delete.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use worktable::prelude::*;
use worktable::worktable;

worktable!(
name: DeleteTest,
columns: {
token: String primary_key,
val1: u64,
val2: u64,
},
indexes: {
val1_idx: val1,
val2_idx: val2,
},
queries: {
update: {
Val1ByToken(val1) by token,
},
delete: {
ByVal1() by val1,
}
}
);
1 change: 1 addition & 0 deletions tests/worktable/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod bench;
mod config;
mod count;
mod custom_pk;
mod delete;
mod float;
mod in_place;
mod index;
Expand Down
169 changes: 169 additions & 0 deletions util/find_println.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
#!/bin/bash

# Script to find println! statements in staged Rust files outside of tests
# Usage: ./find_println.sh [--all-modified]
# Default: Only checks files that are staged (added to git) but not yet committed
# --all-modified: Checks all modified files (staged and unstaged)
# Excludes:
# - Files in tests/ directories
# - Code inside #[cfg(test)] modules
# - Test functions marked with #[test]

set -e

# Parse command line arguments
CHECK_ALL_MODIFIED=false
if [[ "$1" == "--all-modified" ]]; then
CHECK_ALL_MODIFIED=true
fi

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

if [ "$CHECK_ALL_MODIFIED" = true ]; then
echo -e "${BLUE}🔍 Searching for println! statements in all modified files outside of tests...${NC}"
echo

# Get all modified .rs files (staged and unstaged) that are not in tests/ directories
modified_files=$(git diff --name-only HEAD | grep '\.rs$' | grep -v '/tests/' || true)
else
echo -e "${BLUE}🔍 Searching for println! statements in staged files outside of tests...${NC}"
echo

# Get staged .rs files that are not in tests/ directories
modified_files=$(git diff --cached --name-only --diff-filter=AM | grep '\.rs$' | grep -v '/tests/' || true)
fi

if [ -z "$modified_files" ]; then
if [ "$CHECK_ALL_MODIFIED" = true ]; then
echo -e "${GREEN}✅ No modified Rust files found to check${NC}"
else
echo -e "${GREEN}✅ No staged Rust files found to check${NC}"
fi
exit 0
fi

if [ "$CHECK_ALL_MODIFIED" = true ]; then
echo -e "${BLUE}Modified files to check:${NC}"
else
echo -e "${BLUE}Staged files to check:${NC}"
fi
for file in $modified_files; do
echo -e " • $file"
done
echo

rust_files="$modified_files"

total_files=0
files_with_println=0
total_println_count=0

# Track if we're inside a cfg(test) module or test function
in_test_module=0
brace_depth=0
test_module_start_depth=0

for file in $rust_files; do
total_files=$((total_files + 1))
file_has_println=0
println_count=0

# Reset state for each file
in_test_module=0
brace_depth=0
test_module_start_depth=0

line_num=0
while IFS= read -r line || [[ -n "$line" ]]; do
line_num=$((line_num + 1))

# Count braces to track scope depth
open_braces=$(echo "$line" | grep -o '{' | wc -l)
close_braces=$(echo "$line" | grep -o '}' | wc -l)
brace_depth=$((brace_depth + open_braces - close_braces))

# Check if we're entering a cfg(test) module
if echo "$line" | grep -E '^\s*#\s*\[\s*cfg\s*\(\s*test\s*\)\s*\]' > /dev/null; then
# Look ahead to see if next non-empty, non-comment line is a module
temp_line_num=$line_num
found_mod=0
while IFS= read -r next_line; do
temp_line_num=$((temp_line_num + 1))
# Skip empty lines and comments
if echo "$next_line" | grep -E '^\s*(//.*)?$' > /dev/null; then
continue
fi
# Check if it's a module declaration
if echo "$next_line" | grep -E '^\s*mod\s+' > /dev/null; then
found_mod=1
fi
break
done < <(tail -n +$((line_num + 1)) "$file")

if [ $found_mod -eq 1 ]; then
in_test_module=1
test_module_start_depth=$brace_depth
fi
fi

# Check if we're exiting a cfg(test) module
if [ $in_test_module -eq 1 ] && [ $brace_depth -lt $test_module_start_depth ]; then
in_test_module=0
fi

# Skip if we're in a test module
if [ $in_test_module -eq 1 ]; then
continue
fi

# Skip lines that are test functions (simple heuristic)
if echo "$line" | grep -E '^\s*#\s*\[\s*test\s*\]' > /dev/null; then
# Skip the next few lines until we find the function and its body
continue
fi

# Check for println! (but not in comments)
if echo "$line" | grep -E '^\s*[^/]*println!' > /dev/null; then
# Make sure it's not in a comment
if ! echo "$line" | grep -E '^\s*//' > /dev/null; then
if [ $file_has_println -eq 0 ]; then
echo -e "${YELLOW}📁 $file${NC}"
file_has_println=1
files_with_println=$((files_with_println + 1))
fi
echo -e " ${RED}Line $line_num:${NC} $(echo "$line" | sed 's/^[[:space:]]*//')"
println_count=$((println_count + 1))
total_println_count=$((total_println_count + 1))
fi
fi

done < "$file"

if [ $file_has_println -eq 1 ]; then
echo -e " ${GREEN}Found $println_count println! statement(s)${NC}"
echo
fi
done

# Summary
echo -e "${BLUE}📊 Summary:${NC}"
if [ "$CHECK_ALL_MODIFIED" = true ]; then
echo -e " • Modified files scanned: ${total_files}"
else
echo -e " • Staged files scanned: ${total_files}"
fi
echo -e " • Files with println!: ${files_with_println}"
echo -e " • Total println! statements: ${total_println_count}"

if [ $total_println_count -eq 0 ]; then
echo -e "${GREEN}✅ No println! statements found outside of tests!${NC}"
exit 0
else
echo -e "${RED}⚠️ Found println! statements that should be reviewed${NC}"
exit 1
fi
Loading