macro_rules! define_tables {
(
$(
// 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
),* $(,)?
) => { ... };
}
Expand description
Define all table types.
§Purpose
This macro allows you to define all database tables in one place.
A by-product of this macro is that it defines some convenient traits specific to your tables (see Output).
§Inputs
This macro expects a list of tables, and their key/value types.
This syntax is as follows:
cuprate_database::define_tables! {
/// Any extra attributes you'd like to add to
/// this table type, e.g. docs or derives.
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:
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,
}
// 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::<Table1>(&tx_rw)?;
let mut table = env_inner.open_db_rw::<Table1>(&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::<Table1>(&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)?;
}
§Output
This macro:
- Implements
Table
on all your table types - Creates a
pub trait Tables
trait (in scope) - Creates a
pub trait TablesIter
trait (in scope) - Creates a
pub trait TablesMut
trait (in scope) - Blanket implements a
(tuples, containing, all, open, database, tables, ...)
for the above traits - 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: https://github.com/Cuprate/cuprate/pull/102#pullrequestreview-1978348871.
The OpenTables
trait lets you open all tables you’ve defined, at once.
§Example
For examples of usage & output, see
cuprate_blockchain::tables
.