sea-query
sea-orm 自己不拼 SQL。Select<E>、Insert<A> 这些类型里装的是 sea-query 的语句(SelectStatement、InsertStatement…),到 ConnectionTrait::query_one 这一步才调 build,选一个方言写成字符串和参数,最后交给 sqlx。这一部分讲 sea-query 1.0.2 和 sea-query-sqlx 0.9.1 里查询主线经过的三段:语句树、把树写成 SQL 的 QueryBuilder、把参数绑到 sqlx 的 SqlxValues。相关源码:src/query/ 约 8.2k 行(其中 select.rs 3k,2k 行是文档注释里的例子),src/backend/query_builder.rs 2.1k,backend/postgres/ 约 1.6k,sea-query-sqlx/src/sqlx_postgres.rs 387 行。
- 语句是一棵树:四种语句的字段就是 SQL 的各个子句;所有表达式都是一个
Expr枚举(1.0 起SimpleExpr只是它的别名);and_where和cond_where走同一条路,多次调用总是用AND连起来;DynIden是提前渲染好的字符串;语句里没有方言。 - QueryBuilder 与参数:
build和to_string跑的是同一套prepare_*,区别只在SqlWriter::push_param;LIMIT/OFFSET也是参数,Expr::cust、Order::Field、空条件的TRUE/FALSE直接写进 SQL;to_string用E'...'转义字符串、双写标识符里的",但输出丢了参数类型,只适合看。 - 绑到 sqlx:sea-orm 的
Statement经sqlx::query_with(AssertSqlSafe(sql), SqlxValues(values))交给 sqlx;IntoArguments按Value分支选 Rust 类型,None也带着类型(Value::Int(None)在Parse里是 OID 23);含 NULL 元素的数组和超过i64::MAX的u64会在这里 panic。
flowchart TB sel["Select E"] --> tree["SelectStatement 语句树"] tree -->|"build(Postgres)"| qb[PostgresQueryBuilder] qb --> sqlv["SQL 带 $N + Values"] sqlv --> stmt["sea-orm Statement"] stmt --> bind["SqlxValues 绑参数"] bind --> sqlx["sqlx::query_with"]
Select<E> 自己的 API(filter、order_by、limit)在 04 查询;列上的 eq / is_in 怎么产出 Expr、Value 各分支是什么,在列与值。参数到了 sqlx 之后怎么编码、Parse / Bind 怎么发,看 sqlx 卷的类型和扩展查询协议与语句缓存。
💬 关联讨论
发起讨论加载中...