From bf1b76fa288753b5958dec732525dc153fb96fd7 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Tue, 9 Jul 2024 17:34:17 -0400 Subject: [PATCH] docs --- storage/blockchain/src/tables.rs | 4 - storage/database/README.md | 9 ++ storage/database/src/tables.rs | 209 ++++++++++++++++++++++--------- 3 files changed, 162 insertions(+), 60 deletions(-) diff --git a/storage/blockchain/src/tables.rs b/storage/blockchain/src/tables.rs index 4e8d7a3..caac787 100644 --- a/storage/blockchain/src/tables.rs +++ b/storage/blockchain/src/tables.rs @@ -14,12 +14,8 @@ //! # Traits //! This module also contains a set of traits for //! accessing _all_ tables defined here at once. -//! -//! For example, this is the object returned by [`OpenTables::open_tables`]. //---------------------------------------------------------------------------------------------------- Import -use cuprate_database::{DatabaseIter, DatabaseRo, DatabaseRw}; - use crate::types::{ Amount, AmountIndex, AmountIndices, BlockBlob, BlockHash, BlockHeight, BlockInfo, KeyImage, Output, PreRctOutputId, PrunableBlob, PrunableHash, PrunedBlob, RctOutput, TxBlob, TxHash, diff --git a/storage/database/README.md b/storage/database/README.md index d7a9b92..5bcec60 100644 --- a/storage/database/README.md +++ b/storage/database/README.md @@ -80,6 +80,15 @@ and use `` everywhere it is stored instead. This would allow generic-backed dynamic runtime selection of the database backend, i.e. the user can select which database backend they use. --> +# Defining tables +Most likely, your crate building on-top of `cuprate_database` will +want to define all tables used at compile time. + +If this is the case, consider using the [`define_tables`] macro +to bulk generate zero-sized marker types that implement [`Table`]. + +This macro also generates other convenient traits specific to _your_ tables. + # Feature flags Different database backends are enabled by the feature flags: - `heed` (LMDB) diff --git a/storage/database/src/tables.rs b/storage/database/src/tables.rs index ec744a3..c2ac821 100644 --- a/storage/database/src/tables.rs +++ b/storage/database/src/tables.rs @@ -1,58 +1,156 @@ -//! Database tables. -//! -//! # Table marker structs -//! This module contains all the table definitions used by `cuprate_blockchain`. -//! -//! The zero-sized structs here represents the table type; -//! they all are essentially marker types that implement `Table`. -//! -//! Table structs are `CamelCase`, and their static string -//! names used by the actual database backend are `snake_case`. -//! -//! For example: `BlockBlobs` -> `block_blobs`. -//! -//! # Traits -//! This module also contains a set of traits for -//! accessing _all_ tables defined here at once. -//! -//! For example, this is the object returned by `OpenTables::open_tables`. +//! Database table definition macro. //---------------------------------------------------------------------------------------------------- Import //---------------------------------------------------------------------------------------------------- Table macro -/// Create all tables, should be used _once_. +/// Define all table types. /// -/// Generating this macro once and using `$()*` is probably -/// faster for compile times than calling the macro _per_ table. +/// # Purpose +/// This macro allows you to define all database tables in one place. /// -/// All tables are zero-sized table structs, and implement the `Table` trait. +/// A by-product of this macro is that it defines some +/// convenient traits specific to _your_ tables +/// (see [Output](#output)). /// -/// Table structs are automatically `CamelCase`, -/// and their static string names are automatically `snake_case`. +/// # Inputs +/// This macro expects a list of tables, and their key/value types. /// -/// // --- TODO +/// This syntax is as follows: /// -/// Creates: -/// - `pub trait Tables` -/// - `pub trait TablesIter` -/// - `pub trait TablesMut` -/// - Blanket implementation for `(tuples, containing, all, open, database, tables, ...)` +/// ```rust +/// cuprate_database::define_tables! { +/// /// Any extra attributes you'd like to add to +/// /// this table type, e.g. docs or derives. /// -/// For why this exists, see: . +/// 0 => TableName, +/// // ▲ ▲ +/// // │ └─ Table struct name. The macro generates this for you. +/// // │ +/// // Incrementing index. This must start at 0 +/// // and increment by 1 per table added. +/// +/// u8 => u64, +/// // ▲ ▲ +/// // │ └─ Table value type. +/// // │ +/// // Table key type. +/// +/// // Another table. +/// 1 => TableName2, +/// i8 => i64, +/// } +/// ``` +/// +/// An example: +/// ```rust +/// use cuprate_database::{ +/// ConcreteEnv, Table, +/// config::ConfigBuilder, +/// Env, EnvInner, +/// DatabaseRo, DatabaseRw, TxRo, TxRw, +/// }; +/// +/// // This generates `pub struct Table{1,2,3}` +/// // where all those implement `Table` with +/// // the defined name and key/value types. +/// // +/// // It also generate traits specific to our tables. +/// cuprate_database::define_tables! { +/// 0 => Table1, +/// u32 => i32, +/// +/// /// This one has extra docs. +/// 1 => Table2, +/// u64 => (), +/// +/// 2 => Table3, +/// i32 => i32, +/// } +/// +/// # fn main() -> Result<(), Box> { +/// # let tmp_dir = tempfile::tempdir()?; +/// # let db_dir = tmp_dir.path().to_owned(); +/// # let config = ConfigBuilder::new(db_dir.into()).build(); +/// // Open the database. +/// let env = ConcreteEnv::open(config)?; +/// let env_inner = env.env_inner(); +/// +/// // Open the table we just defined. +/// { +/// let tx_rw = env_inner.tx_rw()?; +/// env_inner.create_db::(&tx_rw)?; +/// let mut table = env_inner.open_db_rw::(&tx_rw)?; +/// +/// // Write data to the table. +/// table.put(&0, &1)?; +/// +/// drop(table); +/// TxRw::commit(tx_rw)?; +/// } +/// +/// // Read the data, assert it is correct. +/// { +/// let tx_ro = env_inner.tx_ro()?; +/// let table = env_inner.open_db_ro::(&tx_ro)?; +/// assert_eq!(table.first()?, (0, 1)); +/// } +/// +/// // Create all tables at once using the +/// // `OpenTables` trait generated with the +/// // macro above. +/// { +/// let tx_rw = env_inner.tx_rw()?; +/// env_inner.create_tables(&tx_rw)?; +/// TxRw::commit(tx_rw)?; +/// } +/// +/// // Open all tables at once. +/// { +/// let tx_ro = env_inner.tx_ro()?; +/// let all_tables = env_inner.open_tables(&tx_ro)?; +/// } +/// # Ok(()) } +/// ``` +/// +/// # Output +/// This macro: +/// 1. Implements [`Table`](crate::Table) on all your table types +/// 1. Creates a `pub trait Tables` trait (in scope) +/// 1. Creates a `pub trait TablesIter` trait (in scope) +/// 1. Creates a `pub trait TablesMut` trait (in scope) +/// 1. Blanket implements a `(tuples, containing, all, open, database, tables, ...)` for the above traits +/// 1. Creates a `pub trait OpenTables` trait (in scope) +/// +/// All table types are zero-sized structs that implement the `Table` trait. +/// +/// Table structs are automatically `CamelCase`, and their +/// static string names are automatically `snake_case`. +/// +/// For why the table traits + blanket implementation on the tuple exists, see: +/// . +/// +/// The `OpenTables` trait lets you open all tables you've defined, at once. +/// +/// # Example +/// For examples of usage & output, see +/// [`cuprate_blockchain::tables`](https://github.com/Cuprate/cuprate/blob/main/storage/blockchain/src/tables.rs). #[macro_export] macro_rules! define_tables { ( $( - $(#[$attr:meta])* // Documentation and any `derive`'s. - $index:literal => $table:ident, // The table name + doubles as the table struct name. - $key:ty => // Key type. - $value:ty // Value type. + // Documentation and any `derive`'s. + $(#[$attr:meta])* + + // The table name + doubles as the table struct name. + $index:literal => $table:ident, + + // Key type => Value type. + $key:ty => $value:ty ),* $(,)? ) => { $crate::paste::paste! { $( // Table struct. $(#[$attr])* - // The below test show the `snake_case` table name in cargo docs. #[doc = concat!("- Key: [`", stringify!($key), "`]")] #[doc = concat!("- Value: [`", stringify!($value), "`]")] #[doc = concat!("- Name: `", stringify!([<$table:snake>]), "`")] @@ -68,17 +166,16 @@ macro_rules! define_tables { } )* - /// Object containing all opened [`Table`]s in read-only mode. + /// Object containing all opened [`Table`](cuprate_database::Table)s in read-only mode. /// /// This is an encapsulated object that contains all - /// available [`Table`]'s in read-only mode. + /// available `Table`'s in read-only mode. /// /// It is a `Sealed` trait and is only implemented on a /// `(tuple, containing, all, table, types, ...)`. /// /// This is used to return a _single_ object from functions like - /// [`OpenTables::open_tables`](crate::OpenTables::open_tables) rather - /// than the tuple containing the tables itself. + /// [`OpenTables::open_tables`] rather than the tuple containing the tables itself. /// /// To replace `tuple.0` style indexing, `field_accessor_functions()` /// are provided on this trait, which essentially map the object to @@ -107,17 +204,17 @@ macro_rules! define_tables { /// Access an opened #[doc = concat!("[`", stringify!($table), "`]")] /// database. - fn [<$table:snake>](&self) -> &impl DatabaseRo<$table>; + fn [<$table:snake>](&self) -> &impl $crate::DatabaseRo<$table>; )* /// This returns `true` if all tables are empty. /// /// # Errors /// This returns errors on regular database errors. - fn all_tables_empty(&self) -> Result; + fn all_tables_empty(&self) -> Result; } - /// Object containing all opened [`Table`]s in read + iter mode. + /// Object containing all opened [`Table`](cuprate_database::Table)s in read + iter mode. /// /// This is the same as [`Tables`] but includes `_iter()` variants. /// @@ -130,11 +227,11 @@ macro_rules! define_tables { /// Access an opened read-only + iterable #[doc = concat!("[`", stringify!($table), "`]")] /// database. - fn [<$table:snake _iter>](&self) -> &(impl DatabaseRo<$table> + DatabaseIter<$table>); + fn [<$table:snake _iter>](&self) -> &(impl $crate::DatabaseRo<$table> + $crate::DatabaseIter<$table>); )* } - /// Object containing all opened [`Table`]s in write mode. + /// Object containing all opened [`Table`](cuprate_database::Table)s in write mode. /// /// This is the same as [`Tables`] but for mutable accesses. /// @@ -147,7 +244,7 @@ macro_rules! define_tables { /// Access an opened #[doc = concat!("[`", stringify!($table), "`]")] /// database. - fn [<$table:snake _mut>](&mut self) -> &mut impl DatabaseRw<$table>; + fn [<$table:snake _mut>](&mut self) -> &mut impl $crate::DatabaseRw<$table>; )* } @@ -182,23 +279,23 @@ macro_rules! define_tables { // [...] // ``` $( - [<$table:upper>]: DatabaseRo<$table>, + [<$table:upper>]: $crate::DatabaseRo<$table>, )* { $( // The function name of the accessor function is // the table type in `snake_case`, e.g., `block_info_v1s()`. #[inline] - fn [<$table:snake>](&self) -> &impl DatabaseRo<$table> { + fn [<$table:snake>](&self) -> &impl $crate::DatabaseRo<$table> { // The index of the database table in // the tuple implements the table trait. &self.$index } )* - fn all_tables_empty(&self) -> Result { + fn all_tables_empty(&self) -> Result { $( - if !DatabaseRo::is_empty(&self.$index)? { + if !$crate::DatabaseRo::is_empty(&self.$index)? { return Ok(false); } )* @@ -212,14 +309,14 @@ macro_rules! define_tables { for ($([<$table:upper>]),*) where $( - [<$table:upper>]: DatabaseRo<$table> + DatabaseIter<$table>, + [<$table:upper>]: $crate::DatabaseRo<$table> + $crate::DatabaseIter<$table>, )* { $( // The function name of the accessor function is // the table type in `snake_case` + `_iter`, e.g., `block_info_v1s_iter()`. #[inline] - fn [<$table:snake _iter>](&self) -> &(impl DatabaseRo<$table> + DatabaseIter<$table>) { + fn [<$table:snake _iter>](&self) -> &(impl $crate::DatabaseRo<$table> + $crate::DatabaseIter<$table>) { &self.$index } )* @@ -231,14 +328,14 @@ macro_rules! define_tables { for ($([<$table:upper>]),*) where $( - [<$table:upper>]: DatabaseRw<$table>, + [<$table:upper>]: $crate::DatabaseRw<$table>, )* { $( // The function name of the mutable accessor function is // the table type in `snake_case` + `_mut`, e.g., `block_info_v1s_mut()`. #[inline] - fn [<$table:snake _mut>](&mut self) -> &mut impl DatabaseRw<$table> { + fn [<$table:snake _mut>](&mut self) -> &mut impl $crate::DatabaseRw<$table> { &mut self.$index } )* @@ -247,7 +344,7 @@ macro_rules! define_tables { /// Open all tables at once. /// /// This trait encapsulates the functionality of opening all tables at once. - /// It can be seen as the "constructor" for the `Tables` object. + /// It can be seen as the "constructor" for the [`Tables`] object. /// /// Note that this is already implemented on [`cuprate_database::EnvInner`], thus: /// - You don't need to implement this @@ -260,7 +357,7 @@ macro_rules! define_tables { /// Open all tables in read/iter mode. /// - /// This calls [`EnvInner::open_db_ro`] on all database tables + /// This calls [`cuprate_database::EnvInner::open_db_ro`] on all database tables /// and returns a structure that allows access to all tables. /// /// # Errors