4个版本 (2个破坏性更新)

0.3.0 2024年5月8日
0.2.1 2024年3月25日
0.2.0 2024年3月25日
0.1.0 2023年10月7日

#358数据库接口

GPL-3.0 许可协议

72KB
717

njord

Njord

build crates.io njord: rustc 1.77.1+ njord_derive: rustc 1.77+ discussions

一个轻量且可扩展的Rust ORM库。

目录

支持的数据库

数据库 支持 状态
SQLite 目前支持。
PostgreSQL 不支持,帮助我们实现它吗?
MySQL 不支持,帮助我们实现它吗?
MariaDB 不支持,帮助我们实现它吗?
Oracle 不支持,帮助我们实现它吗?
MSSQL 不支持,帮助我们实现它吗?

入门指南

初始化新项目

首先我们需要生成我们的项目。

cargo new --bin njord_demo

现在,让我们将Njord添加到我们的依赖项中。我们还将使用一个名为.env的工具来管理我们的环境变量。我们也会将其添加到依赖项中。

[dependencies]

# The core APIs, including the Table trait. 
# using #[derive(Table)] to make njord work with structs
# and enums defined in your crate.
njord = { version = "<version>", features = ["sqlite"] }
njord_derive = { version = "<version>" }

添加模式文件

现在,我们需要定义我们的模式文件,它将位于 src/schema.rs 之下。我们将存储基本的结构,这些结构将映射到数据库上。

#[derive(Table)]
#[table_name = "users"]
pub struct User {
    id: usize,
    username: String,
    email: String,
    address: String,
}

#[derive(Table)]
#[table_name = "categories"]
pub struct Category {
    id: usize,
    name: String,
}

#[derive(Table)]
#[table_name = "products"]
pub struct Product {
    id: usize,
    name: String,
    description: String,
    price: f64,
    stock_quantity: usize,
    category: Category,     // one-to-one relationship
    discount: Option<f64>,  // allow for null 
}

#[derive(Table)]
#[table_name = "orders"]
pub struct Order {
    id: usize,
    user: User,             // one-to-one relationship
    products: Vec<Product>, // one-to-many relationship - populates from based on junction table (gets from macro attribute "table_name" and combines them for example, orders_products)
    total_cost: f64,
}

现在我们已经有了这些,我们需要创建SQL以在数据库中设置它并执行它。

-- users table
CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    username TEXT NOT NULL,
    email TEXT NOT NULL,
    address TEXT NOT NULL
);

-- products table
CREATE TABLE products (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    description TEXT NOT NULL,
    price REAL NOT NULL,
    stock_quantity INTEGER NOT NULL,
    category INTEGER REFERENCES categories(id),
    discount: REAL NULL
);

-- orders table
CREATE TABLE orders (
    id INTEGER PRIMARY KEY,
    user_id INTEGER REFERENCES users(id),
    total_cost REAL NOT NULL
);

-- order_products table
CREATE TABLE order_products (
    order_id INTEGER REFERENCES orders(id),
    product_id INTEGER REFERENCES products(id),
    PRIMARY KEY (order_id, product_id)
);

使用方法

那么我们如何建立连接并实际选择或插入数据库中的数据?让我们看看。注意,这些示例可能已经过时,所以不要将其视为真实信息来源。

SQLite

建立连接

要建立连接,我们首先需要调用 sqlite::open() 函数,并用一个match语句使用它。

let db_name = "njord.db";
let db_path = Path::new(&db_name);

match sqlite::open(db_path) {
    Ok(c) => {
        println!("Database opened successfully!");
        
        // Additional logic when we are connected.
        // We need to open a connection and pass it 
        // to the corresponding sqlite function.
    }
    Err(err) => eprintln!("Error opening the database: {}", err),
}

插入数据

let user = User {
    username: String::from("john_doe"),
    email: String::from("[email protected]"),
    address: String::from("123 Main St"),
};

let result = sqlite::insert(c, vec![user]);
assert!(result.is_ok());

生成的SQL

INSERT INTO users (
    username,
    email,
    address
) VALUES (
    'john_doe',
    '[email protected]',
    '123 Main St'
)

更新数据

let columns = vec!["username".to_string(), "address".to_string()];
let where_condition = Condition::Eq("username".to_string(), "john_doe".to_string());

let user = User {
    username: String::from("john_doe_2"),
    email: String::from("[email protected]"),
    address: String::from("1234 Main St"),
};

let mut order = HashMap::new();
order.insert(vec!["id".to_string()], "DESC".to_string());
        
let result = sqlite::update(c, user)
    .set(columns)
    .where_clause(where_condition)
    .order_by(order)
    .limit(4)
    .offset(0)
    .build();

assert!(result.is_ok());

生成的SQL

UPDATE users
SET
    username
WHERE
    username = 'john_doe'
ORDER BY
    id DESC
LIMIT 4
OFFSET 0

删除数据

let where_condition = Condition::Eq("username".to_string(), "john_doe".to_string());

let mut order = HashMap::new();
order.insert(vec!["id".to_string()], "DESC".to_string());

let result = sqlite::delete(c)
    .from(User::default())
    .where_clause(where_condition)
    .order_by(order)
    .limit(20)
    .offset(0)
    .build();

assert!(result.is_ok());

生成的SQL

DELETE FROM users
WHERE
    username = 'john_doe'
ORDER BY
    id DESC
LIMIT 20
OFFSET 0

选择数据

let columns = vec!["id".to_string(), "username".to_string(), "email".to_string(), "address".to_string()];
let where_condition = Condition::Eq("username".to_string(), "john_doe".to_string());
let group_by = vec!["username".to_string(), "address".to_string()];

let mut order_by = HashMap::new();
order_by.insert(vec!["id".to_string()], "ASC".to_string());

let having_condition = Condition::Gt("id".to_string(), "1".to_string());

// Build the query
// We need to pass the struct User with the Default trait in .from()
let result: Result<Vec<User>> = sqlite::select(c, columns)
    .from(User::default())
    .where_clause(where_condition)
    .order_by(order_by)
    .group_by(group_by)
    .having(having_condition)
    .build();

match result {
    Ok(result) => {
        assert_eq!(result.len(), 1);
    }
    Err(error) => panic!("Failed to SELECT: {:?}", error),
};

生成的SQL

SELECT
    id,
    username,
    email,
    address
FROM
    users
WHERE
    username = 'mjovanc'
GROUP BY
    username,
    email
HAVING
    id > 1
ORDER BY
    email DESC

寻求帮助

你在使用Njord时遇到问题吗?我们想要帮助你!

  • 阅读我们文档中的说明。

  • 如果你正在升级,请阅读发布说明以获取升级说明和“新特性”。

  • 在我们的Stack Overflow(https://stackoverflow.com)上提出问题,我们将监控带有Njord标签的问题。

  • https://github.com/mjovanc/njord/issues上报告Njord的bug。

报告问题

Njord使用GitHub的集成问题跟踪系统来记录bug和功能请求。如果你想提出一个问题,请遵循以下建议

  • 在报告bug之前,请搜索问题跟踪器以查看是否有人已经报告了该问题。

  • 如果问题尚不存在,则创建一个新的问题。

  • 请在问题报告中提供尽可能多的信息。我们想知道您使用的Njord版本、操作系统和Rust版本。

  • 如果您需要粘贴代码或包含堆栈跟踪,请使用Markdown。```请将您的文本包围起来。

  • 如果可能,尝试创建一个重现问题的测试用例或项目,并将其附加到问题中。

贡献

在贡献之前,请阅读贡献指南,以获取有关如何开始使用Njord以及提交贡献时应包含的内容的有用信息。

行为准则

任何与Njord在任何空间互动的人,包括但不限于这个GitHub仓库,都必须遵守我们的行为准则。

贡献者

以下贡献者要么帮助启动了这个项目,要么贡献了代码,正在积极维护它(包括文档),或者以其他方式成为这个项目的杰出贡献者。我们想花点时间来认可他们。

mjovanc appelskrutt34

许可协议

BSD 3-Clause许可证。

依赖关系

~23MB
~444K SLoC