Oyelowo / surreal-orm

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

Closed Oyelowo closed 9 months ago

Oyelowo commented 9 months ago

Done

    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));
    };
    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?;


- 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