#sql-query #query-builder #sql #builder #query

scooby

一个具有愉快流畅API的SQL查询构建器,紧密模仿实际的SQL

7个版本 (4个破坏性更改)

0.5.0 2023年8月31日
0.4.0 2021年9月12日
0.3.0 2021年8月30日
0.2.0 2021年8月28日
0.1.2 2021年8月22日

#766数据库接口

Download history 88/week @ 2024-03-13 71/week @ 2024-03-20 96/week @ 2024-03-27 107/week @ 2024-04-03 56/week @ 2024-04-10 97/week @ 2024-04-17 69/week @ 2024-04-24 57/week @ 2024-05-01 89/week @ 2024-05-08 42/week @ 2024-05-15 32/week @ 2024-05-22 28/week @ 2024-05-29 48/week @ 2024-06-05 99/week @ 2024-06-12 114/week @ 2024-06-19 54/week @ 2024-06-26

每月318次下载

MIT/Apache

130KB
3K SLoC

Scooby

Latest Version docs

Scooby是一个具有愉快流畅API的SQL查询构建器,紧密模仿实际的SQL。旨在舒适地构建动态语句,并在顶部添加一些安全检查,以确保您不会忘记像 ON 子句等重要事项。不进行引号处理,也不进行验证。

目前仅支持PostgreSQL语法。

需要Rust 1.54。

有关详细信息和方法示例,请参阅文档

原则

  • 单一职责: 构建SQL语句。其他一切都不在范围内。
  • API设计得尽可能接近实际的SQL,同时略灵活。
  • 一切都是 原始SQL字符串。如果您需要传递用户输入,请使用参数化语句。
  • 在可能的情况下,应在编译时防止 明显的错误
  • 无外部依赖

支持的语句、子句和功能

  1. SELECT

    • WITH
    • WHERE
    • GROUP BY
    • HAVING
    • ALL, DISTINCTDISTINCT ON
    • ORDER BY
      • ASC
      • DESC
      • NULLS FIRST
      • NULLS LAST
    • LIMITOFFSET
    • FROM 与子查询和具有良好API的连接
      • JOIN, INNER JOINCROSS JOIN
      • LEFT JOINLEFT OUTER JOIN
      • RIGHT JOINRIGHT OUTER JOIN
      • FULL JOINFULL OUTER JOIN
  2. INSERT INTO

    • WITH
    • DEFAULT VALUES
    • VALUES具有编译时检查,确保所有值的长度与列相同
    • ON CONFLICT
      • DO NOTHING
      • DO UPDATE SET
    • RETURNING
  3. DELETE FROM

    • WITH
    • WHERE
    • RETURNING
  4. UPDATE

    • WITH
    • SET具有编译时检查,确保您确实设置了一些内容
    • WHERE
    • RETURNING
  5. 方便的x AS y别名

  6. 方便的$1$2... 参数占位符构建器

示例

SELECT

use scooby::postgres::{select, Aliasable, Joinable, Orderable};

// SELECT
//     country.name AS name,
//     COUNT(*) AS count
// FROM
//     Country AS country
//     INNER JOIN City AS city ON city.country_id = country.id
// WHERE
//     city.population > $1
// GROUP BY country.name
// ORDER BY count DESC
// LIMIT 10
select(("country.name".as_("name"), "COUNT(*)".as_("count")))
    .from(
        "Country"
            .as_("country")
            .inner_join("City".as_("city"))
            .on("city.country_id = country.id"),
    )
    .where_("city.population > $1")
    .group_by("country.name")
    .order_by("count".desc())
    .limit(10)
    .to_string();

INSERT INTO

use scooby::postgres::insert_into;

// INSERT INTO Dummy (col1, col2) VALUES (a, b), (c, d), (e, f) RETURNING id
insert_into("Dummy")
    .columns(("col1", "col2"))
    .values([("a", "b"), ("c", "d")])
    .values([("e", "f")])
    .returning("id")
    .to_string();

// INSERT INTO Dummy DEFAULT VALUES
insert_into("Dummy").default_values().to_string();

// INSERT INTO Dummy DEFAULT VALUES ON CONFLICT DO NOTHING
insert_into("Dummy").default_values().on_conflict().do_nothing().to_string();

DELETE FROM

use scooby::postgres::delete_from;

// DELETE FROM Dummy WHERE x > $1 AND y > $2
delete_from("Dummy").where_(("x > $1", "y > $2")).to_string();

WITH (CTE — 常用表表达式)

use scooby::postgres::{with, select};

// WITH regional_sales AS (
//         SELECT region, SUM(amount) AS total_sales
//         FROM orders
//         GROUP BY region
//      ), top_regions AS (
//         SELECT region
//         FROM regional_sales
//         WHERE total_sales > (SELECT SUM(total_sales)/10 FROM regional_sales)
//      )
// SELECT region,
//        product,
//        SUM(quantity) AS product_units,
//        SUM(amount) AS product_sales
// FROM orders
// WHERE region IN (SELECT region FROM top_regions)
// GROUP BY region, product;
with("regional_sales")
    .as_(
        select(("region", "SUM(amount)".as_("total_sales")))
            .from("orders")
            .group_by("region"),
    )
    .and("top_regions")
    .as_(select("region").from("regional_sales").where_(format!(
        "total_sales > ({})",
        select("SUM(total_sales)/10").from("regional_sales")
    )))
    .select((
        "region",
        "product",
        "SUM(quantity)".as_("product_units"),
        "SUM(amount)".as_("product_sales"),
    ))
    .from("orders")
    .where_(format!(
        "region IN ({})",
        select("region").from("top_regions")
    ))
    .group_by(("region", "product"))
    .to_string();

参数

use scooby::postgres::{select, Parameters};

let mut params = Parameters::new();

// SELECT id FROM Thing WHERE x > $1 AND y < $2 AND z IN ($3, $4, $5)
select("id")
    .from("Thing")
    .where_(format!("x > {}", params.next()))
    .where_(format!("y < {}", params.next()))
    .where_(format!("z IN ({})", params.next_n(3)))
    .to_string();

测试

通常

cargo test

为了检查语法

  1. 在您的机器上默认端口运行本地postgresql服务器
  2. cargotest --功能验证-postgres-语法

无运行时依赖项