From 26e27cd7182bad91ee98ea2e17e2eb886d274928 Mon Sep 17 00:00:00 2001 From: nuskey8 <84110981+nuskey8@users.noreply.github.com> Date: Thu, 15 Jan 2026 01:37:21 +0900 Subject: [PATCH 1/4] feat: abort --- native/redb-ffi/src/lib.rs | 13 +++++++++++++ src/Redb/NativeMethods.g.cs | 3 +++ src/Redb/WriteTransaction.cs | 7 ++++++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/native/redb-ffi/src/lib.rs b/native/redb-ffi/src/lib.rs index 808ade8..91e1870 100644 --- a/native/redb-ffi/src/lib.rs +++ b/native/redb-ffi/src/lib.rs @@ -360,6 +360,19 @@ pub extern "C" fn redb_write_tx_delete_table(tx: *mut c_void, name: *const c_cha } } +#[unsafe(no_mangle)] +pub extern "C" fn redb_write_tx_abort(tx: *mut c_void) -> i32 { + let tx = unsafe { + assert!(!tx.is_null()); + Box::from_raw(tx as *mut redb::WriteTransaction) + }; + + match tx.abort() { + Ok(_) => REDB_OK, + Err(_) => REDB_ERROR_STORAGE_ERROR, + } +} + #[unsafe(no_mangle)] pub extern "C" fn redb_insert( table: *mut c_void, diff --git a/src/Redb/NativeMethods.g.cs b/src/Redb/NativeMethods.g.cs index 618e8c3..61c741b 100644 --- a/src/Redb/NativeMethods.g.cs +++ b/src/Redb/NativeMethods.g.cs @@ -82,6 +82,9 @@ internal static unsafe partial class NativeMethods [DllImport(__DllName, EntryPoint = "redb_write_tx_delete_table", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] internal static extern int redb_write_tx_delete_table(void* tx, byte* name); + [DllImport(__DllName, EntryPoint = "redb_write_tx_abort", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern int redb_write_tx_abort(void* tx); + [DllImport(__DllName, EntryPoint = "redb_insert", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] internal static extern int redb_insert(void* table, byte* key, nuint key_len, byte* value, nuint value_len); diff --git a/src/Redb/WriteTransaction.cs b/src/Redb/WriteTransaction.cs index a71bf2b..3790dd4 100644 --- a/src/Redb/WriteTransaction.cs +++ b/src/Redb/WriteTransaction.cs @@ -90,11 +90,16 @@ public void Commit() tx = null; } + public void Dispose() { if (tx != null) { - NativeMethods.redb_free_write_transaction(tx); + var code = NativeMethods.redb_write_tx_abort(tx); + if (code != 0) + { + throw new RedbDatabaseException("Failed to abort transaction", code); + } tx = null; } } From 6cafe47c2e2c73d533a12a2a91a8b7ef516e1972 Mon Sep 17 00:00:00 2001 From: nuskey8 <84110981+nuskey8@users.noreply.github.com> Date: Thu, 15 Jan 2026 01:38:12 +0900 Subject: [PATCH 2/4] rename: redb_commi --- native/redb-ffi/src/lib.rs | 2 +- src/Redb/NativeMethods.g.cs | 4 ++-- src/Redb/WriteTransaction.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/native/redb-ffi/src/lib.rs b/native/redb-ffi/src/lib.rs index 91e1870..1aef7de 100644 --- a/native/redb-ffi/src/lib.rs +++ b/native/redb-ffi/src/lib.rs @@ -403,7 +403,7 @@ pub extern "C" fn redb_insert( } #[unsafe(no_mangle)] -pub extern "C" fn redb_commit(tx: *mut c_void) -> i32 { +pub extern "C" fn redb_write_tx_commit(tx: *mut c_void) -> i32 { let tx = unsafe { assert!(!tx.is_null()); Box::from_raw(tx as *mut redb::WriteTransaction) diff --git a/src/Redb/NativeMethods.g.cs b/src/Redb/NativeMethods.g.cs index 61c741b..debae2c 100644 --- a/src/Redb/NativeMethods.g.cs +++ b/src/Redb/NativeMethods.g.cs @@ -88,8 +88,8 @@ internal static unsafe partial class NativeMethods [DllImport(__DllName, EntryPoint = "redb_insert", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] internal static extern int redb_insert(void* table, byte* key, nuint key_len, byte* value, nuint value_len); - [DllImport(__DllName, EntryPoint = "redb_commit", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - internal static extern int redb_commit(void* tx); + [DllImport(__DllName, EntryPoint = "redb_write_tx_commit", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern int redb_write_tx_commit(void* tx); [DllImport(__DllName, EntryPoint = "redb_begin_read", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] internal static extern int redb_begin_read(void* db, void** @out); diff --git a/src/Redb/WriteTransaction.cs b/src/Redb/WriteTransaction.cs index 3790dd4..120a285 100644 --- a/src/Redb/WriteTransaction.cs +++ b/src/Redb/WriteTransaction.cs @@ -82,7 +82,7 @@ readonly Table OpenTableCore(NullTerminatedUtf8Strin public void Commit() { - var code = NativeMethods.redb_commit(tx); + var code = NativeMethods.redb_write_tx_commit(tx); if (code != 0) { throw new RedbDatabaseException("Failed to commit transaction", code); From 00b30778a6eeb2ef3344dfeddaeb33bda00da259 Mon Sep 17 00:00:00 2001 From: nuskey8 <84110981+nuskey8@users.noreply.github.com> Date: Thu, 15 Jan 2026 01:40:23 +0900 Subject: [PATCH 3/4] feat: set_two_phase_commit/set_quick_repair --- src/Redb/WriteTransaction.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/Redb/WriteTransaction.cs b/src/Redb/WriteTransaction.cs index 120a285..c8acb94 100644 --- a/src/Redb/WriteTransaction.cs +++ b/src/Redb/WriteTransaction.cs @@ -22,6 +22,24 @@ public readonly void SetDurability(RedbDurability durability) } } + public readonly void SetTwoPhaseCommit(bool enable) + { + var code = NativeMethods.redb_write_tx_set_two_phase_commit(tx, enable); + if (code != 0) + { + throw new RedbDatabaseException("Failed to call set_two_phase_commit()", code); + } + } + + public readonly void SetQuickRepair(bool enable) + { + var code = NativeMethods.redb_write_tx_set_quick_repair(tx, enable); + if (code != 0) + { + throw new RedbDatabaseException("Failed to call set_quick_repair()", code); + } + } + public readonly Table OpenTable(ReadOnlySpan name) { using var nameBuffer = new NullTerminatedUtf8String(name); From a8d29d3705db9e2eb820d6388de318acacefaadd Mon Sep 17 00:00:00 2001 From: nuskey8 <84110981+nuskey8@users.noreply.github.com> Date: Thu, 15 Jan 2026 01:44:28 +0900 Subject: [PATCH 4/4] feat: rename/delete table --- native/redb-ffi/src/lib.rs | 67 +++++++++++++++++++++++++----------- src/Redb/NativeMethods.g.cs | 9 +++-- src/Redb/WriteTransaction.cs | 51 +++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 23 deletions(-) diff --git a/native/redb-ffi/src/lib.rs b/native/redb-ffi/src/lib.rs index 1aef7de..4f2258c 100644 --- a/native/redb-ffi/src/lib.rs +++ b/native/redb-ffi/src/lib.rs @@ -349,12 +349,39 @@ pub extern "C" fn redb_write_tx_delete_table(tx: *mut c_void, name: *const c_cha }; let str_slice = c_str.to_str().unwrap(); - let table = match tx.open_table(TableDefinition::<&[u8], &[u8]>::new(str_slice)) { - Ok(table) => table, - Err(err) => return table_error_code(&err), + match tx.delete_table(TableDefinition::<&[u8], &[u8]>::new(str_slice)) { + Ok(_) => REDB_OK, + Err(err) => table_error_code(&err), + } +} + +#[unsafe(no_mangle)] +pub extern "C" fn redb_write_tx_rename_table( + tx: *mut c_void, + old_name: *const c_char, + new_name: *const c_char, +) -> i32 { + let tx = unsafe { + assert!(!tx.is_null()); + &mut *(tx as *mut redb::WriteTransaction) + }; + + let old_c_str = unsafe { + assert!(!old_name.is_null()); + std::ffi::CStr::from_ptr(old_name) + }; + let old_str_slice = old_c_str.to_str().unwrap(); + + let new_c_str = unsafe { + assert!(!new_name.is_null()); + std::ffi::CStr::from_ptr(new_name) }; + let new_str_slice = new_c_str.to_str().unwrap(); - match tx.delete_table(table) { + match tx.rename_table( + TableDefinition::<&[u8], &[u8]>::new(old_str_slice), + TableDefinition::<&[u8], &[u8]>::new(new_str_slice), + ) { Ok(_) => REDB_OK, Err(err) => table_error_code(&err), } @@ -373,6 +400,22 @@ pub extern "C" fn redb_write_tx_abort(tx: *mut c_void) -> i32 { } } +#[unsafe(no_mangle)] +pub extern "C" fn redb_write_tx_commit(tx: *mut c_void) -> i32 { + let tx = unsafe { + assert!(!tx.is_null()); + Box::from_raw(tx as *mut redb::WriteTransaction) + }; + + match tx.commit() { + Ok(_) => REDB_OK, + Err(err) => match err { + redb::CommitError::Storage(_) => REDB_ERROR_STORAGE_ERROR, + _ => todo!(), + }, + } +} + #[unsafe(no_mangle)] pub extern "C" fn redb_insert( table: *mut c_void, @@ -402,22 +445,6 @@ pub extern "C" fn redb_insert( } } -#[unsafe(no_mangle)] -pub extern "C" fn redb_write_tx_commit(tx: *mut c_void) -> i32 { - let tx = unsafe { - assert!(!tx.is_null()); - Box::from_raw(tx as *mut redb::WriteTransaction) - }; - - match tx.commit() { - Ok(_) => REDB_OK, - Err(err) => match err { - redb::CommitError::Storage(_) => REDB_ERROR_STORAGE_ERROR, - _ => todo!(), - }, - } -} - #[unsafe(no_mangle)] pub extern "C" fn redb_begin_read(db: *mut c_void, out: *mut *mut c_void) -> i32 { let db = unsafe { diff --git a/src/Redb/NativeMethods.g.cs b/src/Redb/NativeMethods.g.cs index debae2c..fb5414a 100644 --- a/src/Redb/NativeMethods.g.cs +++ b/src/Redb/NativeMethods.g.cs @@ -82,15 +82,18 @@ internal static unsafe partial class NativeMethods [DllImport(__DllName, EntryPoint = "redb_write_tx_delete_table", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] internal static extern int redb_write_tx_delete_table(void* tx, byte* name); + [DllImport(__DllName, EntryPoint = "redb_write_tx_rename_table", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern int redb_write_tx_rename_table(void* tx, byte* old_name, byte* new_name); + [DllImport(__DllName, EntryPoint = "redb_write_tx_abort", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] internal static extern int redb_write_tx_abort(void* tx); - [DllImport(__DllName, EntryPoint = "redb_insert", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - internal static extern int redb_insert(void* table, byte* key, nuint key_len, byte* value, nuint value_len); - [DllImport(__DllName, EntryPoint = "redb_write_tx_commit", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] internal static extern int redb_write_tx_commit(void* tx); + [DllImport(__DllName, EntryPoint = "redb_insert", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern int redb_insert(void* table, byte* key, nuint key_len, byte* value, nuint value_len); + [DllImport(__DllName, EntryPoint = "redb_begin_read", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] internal static extern int redb_begin_read(void* db, void** @out); diff --git a/src/Redb/WriteTransaction.cs b/src/Redb/WriteTransaction.cs index c8acb94..0bbfd4d 100644 --- a/src/Redb/WriteTransaction.cs +++ b/src/Redb/WriteTransaction.cs @@ -98,6 +98,57 @@ readonly Table OpenTableCore(NullTerminatedUtf8Strin return new Table(database, table); } + public readonly void DeleteTable(ReadOnlySpan utf8Name) + { + using var nameBuffer = new NullTerminatedUtf8String(utf8Name); + DeleteTableCore(nameBuffer); + } + + public readonly void DeleteTable(ReadOnlySpan name) + { + using var nameBuffer = new NullTerminatedUtf8String(name); + DeleteTableCore(nameBuffer); + } + + readonly void DeleteTableCore(NullTerminatedUtf8String name) + { + fixed (byte* namePtr = name) + { + int code = NativeMethods.redb_write_tx_delete_table(tx, namePtr); + if (code != 0) + { + throw new RedbDatabaseException("Failed to delete table", code); + } + } + } + + public readonly void RenameTable(ReadOnlySpan oldUtf8Name, ReadOnlySpan newUtf8Name) + { + using var oldNameBuffer = new NullTerminatedUtf8String(oldUtf8Name); + using var newNameBuffer = new NullTerminatedUtf8String(newUtf8Name); + RenameTableCore(oldNameBuffer, newNameBuffer); + } + + public readonly void RenameTable(ReadOnlySpan oldName, ReadOnlySpan newName) + { + using var oldNameBuffer = new NullTerminatedUtf8String(oldName); + using var newNameBuffer = new NullTerminatedUtf8String(newName); + RenameTableCore(oldNameBuffer, newNameBuffer); + } + + readonly void RenameTableCore(NullTerminatedUtf8String oldName, NullTerminatedUtf8String newName) + { + fixed (byte* oldNamePtr = oldName) + fixed (byte* newNamePtr = newName) + { + int code = NativeMethods.redb_write_tx_rename_table(tx, oldNamePtr, newNamePtr); + if (code != 0) + { + throw new RedbDatabaseException("Failed to rename table", code); + } + } + } + public void Commit() { var code = NativeMethods.redb_write_tx_commit(tx);