Powerful & expressive ORM/query-builder/static checker for raw queries/Fully Automated migration tooling , designed to offer an intuitive API, strict type-checking, novel features, & full specification support. It provides a fresh perspective in data management. Currently supports SurrealDB engine. RDMSs(PG, MYSQL etc) and others coming soon
85
stars
2
forks
source link
52 re implement query turbo transaction and block macros using procedural macro over macro rules #53
Implement query_turbo! for handling extremely complex queries at compile-time. Dynamically supports query_chain, transaction, and block. The difference being that transaction begins with begin transaction; and ends with cancel transaction; or commit transaction; while block is surrounded by curly braces and typically returns a value which can also be a statement.
let db = Surreal::new::<Mem>(()).await.unwrap();
db.use_ns("test").use_db("test").await.unwrap();
let id1 = &Account::create_id("one".to_string());
let id2 = &Account::create_id("two".to_string());
let amount_to_transfer = 300.00;
let acc = Account::schema();
let account::Schema { balance, .. } = Account::schema();
// NOTE: This is not native rust.
let query_chain = query_turbo! {
let balance1 = create_only().content(Balance {
id: Balance::create_id("balance1".to_string()),
amount: amount_to_transfer,
});
create_only().content(Balance {
id: Balance::create_id("balance2".to_string()),
amount: amount_to_transfer,
});
if balance.greater_than(100) {
let first_name = "Oyelowo";
let score = 100;
select(All).from(Account::table_name()).where_(acc.balance.eq(5));
} else if balance.less_than(100) {
let first_name = "Oyelowo";
let score = 100;
select(All).from(Account::table_name()).where_(acc.balance.eq(5));
} else if balance.gte(100) {
let first_name = "Oyelowo";
let score = 100;
select(All).from(Account::table_name()).where_(acc.balance.eq(5));
} else {
let first_name = "Oyelowo";
let score = 100;
select(All).from(Account::table_name()).where_(acc.balance.eq(5));
};
for name in vec!["Oyelowo", "Oyedayo"] {
let first = "Oyelowo";
select(All).from(Account::table_name()).where_(acc.balance.eq(5));
let good_stmt = select(All).from(Account::table_name()).where_(acc.balance.eq(64));
if balance.gt(50) {
let first_name = "Oyelowo";
};
select(All).from(Account::table_name()).where_(acc.balance.eq(34));
let numbers = vec![23, 98];
for age in numbers {
let score = 100;
let first_stmt = select(All).from(Account::table_name()).where_(acc.balance.eq(5));
let second_stmt = select(All).from(Account::table_name()).where_(acc.balance.eq(25));
select(All).from(Account::table_name()).where_(acc.balance.eq(923));
};
};
let balance3 = create().content(Balance {
id: Balance::create_id("balance3".into()),
amount: amount_to_transfer,
});
let accounts = select(All)
.from(id1..=id2);
// You can reference the balance object by using the $balance variable and pass the amount
// as a parameter to the decrement_by function. i.e $balance.amount
let updated1 = update::<Account>(id1).set(acc.balance.increment_by(balance1.with_path::<Balance>(E).amount));
update::<Account>(id1).set(acc.balance.increment_by(balance1.with_path::<Balance>(E).amount));
update::<Account>(id1).set(acc.balance.increment_by(45.3));
// You can also pass the amount directly to the decrement_by function. i.e 300.00
update::<Account>(id2).set(acc.balance.decrement_by(amount_to_transfer));
update::<Account>(id2).set(acc.balance.decrement_by(50));
};
Improve and Implement transaction! macro as procedural macro rather than declarative macro rules.
transaction! now allows option to not bind a variable.
let db = Surreal::new::<Mem>(()).await.unwrap();
db.use_ns("test").use_db("test").await.unwrap();
let id1 = &Account::create_id("one".to_string());
let id2 = &Account::create_id("two".to_string());
let amount_to_transfer = 300.00;
let acc = Account::schema();
transaction! {
BEGIN TRANSACTION;
let balance = create_only().content(Balance {
id: Balance::create_id("balance1".into()),
amount: amount_to_transfer,
});
create_only().content(Account {
id: id1.clone(),
balance: 135_605.16,
});
create_only().content(Account {
id: id2.clone(),
balance: 91_031.31,
});
// You can reference the balance object by using the $balance variable and pass the amount
// as a parameter to the decrement_by function. i.e $balance.amount
update::<Account>(id1).set(acc.balance.increment_by(balance.with_path::<Balance>(E).amount));
// You can also pass the amount directly to the decrement_by function. i.e 300.00
update::<Account>(id2).set(acc.balance.decrement_by(amount_to_transfer));
COMMIT TRANSACTION;
}
.run(db.clone())
.await?;
Implement block! macro as procedural macro for more robustness. Was previously implemented as macro rules and had some limitations.
let created_stats_statement = create::<WeaponStats>().set(object_partial!(WeaponStats {
averageStrength: block! {
let strengths = select_value(strength).from(weapon);
let total = math::sum!(strengths); // 105
let count = array::len!(strengths); // 15
return math::ceil!((((total / count) * (count * total)) / (total + 4)) * 100);
}
}));
- Implemented `define_function!` as proc macro rather than macro rules. Also support very/any complex types as function arguments.
- `query_turbo!`, `transaction!` and `block!` all now support native, `let, if else, for loop, standalone expression and return` statements. Also allows using external closure/function within iteration iterable and for loop conditional expression.
- Implement standalone `for!` loop macro. Although, you are encouraged to use a native-like for loop within `query_turbo`, `transaction` or `block` instead.
- Fixed transaction tests by replacing `count!` function with `array::len!` for counting array items.
- Reorganization and restructuring
- Deprecated declarative macro rules version of `transaction`, `block`, `define_function!` and `for_!` loops. They are all now sufficed with `_deprecated` e,g `transaction_deprecated`.
- Fixed conditionals `let` statement binding in `if else` conditional expression. Was previously including the entire `let` expression rather than just the bound variable parameter when referenced.
- Support native-like division and multiplication autobinding for let statements
Done
query_chain
,transaction
, andblock
. The difference being that transaction begins withbegin transaction;
and ends withcancel transaction;
orcommit transaction;
whileblock
is surrounded by curly braces and typically returns a value which can also be a statement.transaction!
macro as procedural macro rather than declarative macro rules.transaction!
now allows option to not bind a variable.block!
macro as procedural macro for more robustness. Was previously implemented as macro rules and had some limitations.