Coder Social home page Coder Social logo

qjack's Introduction

qjack

ergonomic sqlx wrapper for nightly Rust

  • nightly only
  • macro free
  • available DB:PostgreSQL, MySQL, SQLite
  • available runtime:tokio, async-std

qjack build check status


Sample; How to use

[dependencies]
qjack = { version = "0.1", features = ["rt_tokio", "db_postgres"] }
tokio = { version = "1", features = ["macros"] }

part of sample/src/bin/friends.rs

#[derive(Model, Debug)]
struct Friend {
    id:       i32,
    name:     String,
    password: String,
}

impl Friend {
    async fn create_table_if_not_exists() -> Result<()> {
        q("CREATE TABLE IF NOT EXISTS friends (
            id SERIAL PRIMARY KEY,
            name VARCHAR(32) NOT NULL,
            password VARCHAR(64) NOT NULL
        )").await?; Ok(())
    }

    async fn find_by_id(id: i32) -> Result<Self> {
        q(Self::one("
            SELECT id, name, password FROM friends
            WHERE id = $1
        "), id).await
    }

    async fn search_by_password(password: &str) -> Result<Option<Self>> {
        q(Self::optional("
            SELECT id, name, password FROM friends
            WHERE password = $1
        "), password).await
    }

    async fn find_all_with_limit_by_name_like(like: &str, limit: i32) -> Result<Vec<Friend>> {
        q(Self::all("
            SELECT id, name, password FROM friends
            WHERE name LIKE $1
            LIMIT $2
        "), like, limit).await
    }

    async fn create_many(name_passwords: impl IntoIterator<Item = (String, String)>) -> Result<()> {
        let mut name_passwords = name_passwords.into_iter();

        let mut insert = String::from("INSERT INTO friends (name, password) VALUES");
        if let Some((first_name, first_password)) = name_passwords.next() {
            insert.push_str(&format!(" ('{first_name}', '{first_password}')"))
        } else {return Ok(())}
        for (name, password) in name_passwords {
            insert.push_str(&format!(", ('{name}', '{password}')"))
        }

        q(&*insert).await?; Ok(())
    }
}

#[tokio::main]
async fn main() -> Result<()> {
    q.jack("postgres://qjack:password@postgres:5432/db")
        .max_connections(42)
        .await?;
    println!("Hi, jacked!");

    Friend::create_table_if_not_exists().await?;

    // ...

part of sample/src/bin/transfer.rs

#[derive(Model, Debug)]
struct Account {
    id:      i64,
    name:    String,
    balance: i64,
}

impl Account {
    async fn create_table_if_not_exists() -> Result<()> {
        q("CREATE TABLE IF NOT EXISTS accounts (
            id BIGSERIAL PRIMARY KEY,
            name VARCHAR(32) NOT NULL,
            balance INT8 DEFAULT 0
        )").await?; Ok(())
    }

    async fn create_new(name: &str) -> Result<Self> {
        let created = q(Self::one("
            INSERT INTO accounts
            (name, balance) VALUES ($1, $2)
            RETURNING id, name, balance
        "), name, 0).await?;

        Ok(created)
    }

    async fn gets_income(&mut self, income: i64) -> Result<()> {
        q("UPDATE accounts
            SET balance = balance + $1
            WHERE id = $2
        ", income, &self.id).await?;

        self.balance += income;

        Ok(())
    }

    // transaction is unsafe in current version
    async unsafe fn transfer_to(
        &mut self,
        payee: &mut Account,
        ammount: i64
    ) -> Result<()> {
        q.transaction(|mut x| async {
            if let Err(e) = x("
                UPDATE accounts
                SET balance = balance - $1
                WHERE id = $2
            ", &ammount, &self.id).await {
                eprintln!("Failed to subtract balance: {e}");
                return x.rollback().await
            }

            if let Err(e) = x("
                UPDATE accounts
                SET balance = balance + $1
                WHERE id = $2
            ", &ammount, &payee.id).await {
                eprintln!("Failed to add balance: {e}");
                return x.rollback().await
            }

            self.balance  -= ammount;
            payee.balance += ammount;

            x.commit().await
        }).await
    }
}

#[tokio::main]
async fn main() -> Result<()> {
    q.jack("postgres://qjack:password@postgres:5432/db").await?;

    // ...

q magic

q.jack("DB_URL") /* config */ .await?

creates connection pool in background. All queries must be performed after this.


q.transaction(|mut x| async {
    /*
        returns
            x.rollback().await
        or
            x.commit().await
    */
}).await?

performs a transaction. This is unsafe in current version.


q("query string" /* , params, ... */ ).await?

executes a non-fetch query. This returns QueryResult.


q( M::one("query string") /* , params, ... */ ).await?
q( M::all("query string") /* , params, ... */ ).await?
q( M::optional("query string") /* , params, ... */ ).await?

executes a fetch query. Return type:

  • oneM
  • allVec<M>
  • optionalOption<M>

( Here M means a struct that impls Model )


LICENSE

qjack is licensed under MIT LICENSE (LICENSE or https://opensource.org/licenses/MIT)

qjack's People

Contributors

kanarus avatar

Stargazers

 avatar Shujaat Ali Khan avatar

Watchers

 avatar

Forkers

rustworks

qjack's Issues

TODO

  • support tupple struct in Model
  • test q.transaction and make it not unsafe

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.