大更新:

1、完善SQL语法
2、移除node前端,只保留静态资源
3、写好安装脚本
4、做好linux适配
This commit is contained in:
LIm1tZz7 committed 2026-10-01 20:48:38 +08:00
1 parent 687c012841
commit df6d348995
166 files changed
+16317 -10763

No files matched your search

+42
View File
@@ -0,0 +1,42 @@
# 架构与组件
ChuSQL 由三个可执行文件组成,共用同一份配置:
| 组件 | 作用 |
| ------------------ | ------------------------------------------------------- |
| `chusql-storage` | 存储进程:页面与索引、WAL、崩溃恢复 |
| `chusql-web` | Web 管理端:REST 接口 + 浏览器里的数据库 IDE |
| `csql` | 命令行客户端 |
## 数据流
SQL → 前端(`chusql-web` 或 `csql`)→ 本地端点 → `chusql-storage` → 磁盘。
Web 与命令行是两个并列的前端:Web 走 HTTP,命令行直连本地端点,两者共用同一份
[`chusql.toml`](config.md)、同一个管理员账号与同一张账号表——任意一端改的账号与权限,
另一端立刻生效。
## 一次请求经过什么
1. 浏览器或命令行发起 SQL;
2. 解析与语义检查(表/列是否存在、类型是否匹配、权限是否足够)在这里完成,不合格的语句不会落到磁盘;
3. 合格语句通过本地端点交给 `chusql-storage`;
4. 存储进程读写页面与索引,写之前先记 WAL;
5. 结果原路返回。
## 本地端点
前端与存储进程之间只有一个端点,由 `[server] pipe_name` 决定:Windows 是具名管道,
Linux / macOS 是套接字文件(规则见 [config.md](config.md) 的「端点」一节)。
## 数据在哪里
数据都在 `[storage] data_dir` 下。不写这个键就按平台惯例:Windows `%LOCALAPPDATA%\ChuSQL\data`,
Linux / macOS `${XDG_DATA_HOME:-~/.local/share}/chusql/data`。
| 目录 | 内容 |
| --------------------- | ---------------------------- |
| `system/` | 系统库:账号表与角色授权表 |
| `databases/<库名>/` | 各自建的库 |
服务启动后只建 `system`,**没有默认工作库**;其余库由你自己 `CREATE DATABASE` 创建。
+142
View File
@@ -0,0 +1,142 @@
# 命令与选项
## 一共有几个可执行文件
| 命令 | 作用 | 选项 |
| ---- | ---- | ---- |
| `chusql-storage` | 存储进程:页面与索引、WAL | 只有 `--config <path>` |
| `chusql-web` | Web 管理端:REST 接口 + 浏览器里的数据库 IDE | 见「`chusql-web` 选项」 |
| `csql` | 命令行客户端,直连存储进程,不经过 HTTP | 见「`csql` 选项」 |
| `csql-web` | 一键启动器:按配置拉起存储进程 + Web,日志写 `<install-dir>/logs` | 无选项(`host`/`port` 从配置读) |
四个命令共用同一份 [`chusql.toml`](config.md);`--config` 都是用来临时读另一份配置的。
## `csql` 选项
csql [options]
| 选项 | 默认 | 说明 |
| ---- | ---- | ---- |
| `-u, --user USER` | 配置里的管理员 | 用这个账号登录 |
| `-p, --password` | — | 强制交互输入口令,忽略配置里的 |
| `-d, --database DB` | 不选(启动后没有默认库) | 登录后直接选中哪个库 |
| `-f, --format FORMAT` | `table` | 输出格式:`table` / `json` / `csv` |
| `-e, --execute SQL` | — | 跑一条语句就退出(脚本化用) |
| `--history FILE` | `~/.chusql_history` | 历史文件位置 |
| `--pipe NAME` | 配置 `[server] pipe_name` | 端点名(Windows 具名管道 / Unix 套接字文件) |
| `--storage SERVER` | — | 端点没人应答时,拉起这个存储进程可执行文件 |
| `--config FILE` | 固定位置的 `chusql.toml` | 读另一份配置 |
| `-h, --help` | — | 帮助 |
脚本化示例:
csql -e "SELECT count(*) FROM orders" -f json
csql -u analyst -p -d sales -f csv -e "SELECT * FROM orders LIMIT 5"
## 交互模式
- 提示符 `chusql>`;语句以**分号**结尾,可以跨多行;上下键翻历史(默认存 `~/.chusql_history`)。
- 退出码:语句出错时非 0,方便在脚本里判断。
### 元命令
| 元命令 | 作用 |
| ------ | ---- |
| `\q` `\quit` | 退出 |
| `\?` `\h` `\help` | 帮助 |
| `\l` `\list` | 列出数据库 |
| `\dt` `\d` | 列出当前库的表 |
| `\d <表>` | 看表结构 |
| `\dr` `\roles` | 角色总览:授权对象与成员(管理员专属,等价于 Web 的 `GET /api/roles`) |
| `\c <库>` | 切换数据库 |
| `\f` `\format <fmt>` | 切换输出格式:`table` / `json` / `csv` |
普通身份用 `\dt` 时只会看到自己有 `SELECT` 权限的表,系统表永远不出现。
## 账号与权限
账号:root(配置里的 `user` / `password` 决定,见 [config.md](config.md))是管理员,其余都是普通账号,
默认**零权限**,只能看到被授权的表。系统库 `system`(账号表在里面)只有管理员能进。
服务启动后**只有系统库**,没有任何默认工作库:自己 `CREATE DATABASE shop` 再 `USE shop`。
没选库时只有"限定名"语句能跑(`SELECT * FROM shop.items`),裸表名(`SELECT * FROM items`)会报
`no database selected`——先把库选上。
CREATE USER alice IDENTIFIED BY 'secret'; -- 普通账号,口令是明文,服务端加盐派生
ALTER USER alice IDENTIFIED BY 'new-secret'; -- 改口令
DROP USER alice;
`CREATE USER` / `ALTER USER` / `DROP USER` 只有管理员能执行(Web 端在 SQL 控制台,命令行直接跑)。
权限按**角色**给,三句话:
CREATE ROLE analyst; -- 建角色(平的角色,不可继承)
GRANT SELECT, INSERT ON orders TO analyst; -- 授权:对象可以是表名或 *
GRANT analyst TO alice; -- 把角色给账号
REVOKE INSERT ON orders FROM analyst; -- 收回权限
REVOKE analyst FROM alice; -- 收回角色
DROP ROLE analyst;
| 权限 | 覆盖 |
| ---- | ---- |
| `SELECT` | `SELECT`(含 JOIN、投影、`WHERE` 里的子查询) |
| `INSERT` | `INSERT`(含 `VALUES` 里的子查询) |
| `UPDATE` | `UPDATE`(含赋值与 `WHERE` 里的子查询) |
| `DELETE` | `DELETE`(含 `WHERE` 里的子查询) |
| `ALL` | 上面四种,等价于逐条授权 |
- 对象写 `*` 表示当前库里所有表;写表名时按**当前库**限定(在 `sales` 库执行 `GRANT ... ON orders`
授权的是 `sales.orders`),换库要重新授权。
- 管理员(root)隐式拥有全部权限,不用授权;DDL(建表、建索引等)一律只有管理员能做。
- 角色语句本身只有管理员能跑;普通账号跑 `\dr` / `GET /api/roles` 会被拒(`administrator required`)。
- 授权变更立即生效;已经登录的会话不会被踢下线。
- 当前限制:没有列级授权,没有 `WITH GRANT OPTION`,角色不可继承,也没有自助查询(普通账号不能自己
看自己的授权,得问管理员)。
Web 端对应的接口是 `/api/roles` 系列(`GET` 列表、`POST` 建角色、`DELETE /api/roles/:name` 删角色、
`POST/DELETE /api/roles/:name/grants` 授权/收权、`POST/DELETE /api/roles/:name/members[/:user]` 成员),
全部管理员专属。
## `chusql-web` 选项
chusql-web [options]
| 选项 | 对应配置键 | 默认 |
| ---- | ---------- | ---- |
| `--config FILE` | — | 固定位置的 `chusql.toml` |
| `--host H` | `[web] host` | `127.0.0.1` |
| `--port N` | `[web] port` | `7777` |
| `--static DIR` | `[web] static_dir` | `static` |
| `--user NAME` | `[web] user` | `root` |
| `--storage SERVER` | `[web] storage_server` | — |
| `--cookie-secure BOOL` | `[web] cookie_secure` | `false` |
| `--body-limit N` | `[web] body_limit` | `65536` |
| `--session-idle N` | `[web] session_idle` | `28800` |
| `--session-max N` | `[web] session_max` | `86400` |
| `--login-max-attempts N` | `[web] login_max_attempts` | `5` |
| `--login-window N` | `[web] login_window` | `300` |
| `--page-size N` | `[web] rows_per_page` | `25` |
| `--max-page-size N` | `[web] max_page_size` | `500` |
| `--max-rows N` | `[web] max_rows` | `1000` |
| `--max-sql-length N` | `[web] max_sql_length` | `20000` |
| `--seed BOOL` | `[web] seed` | `false` |
| `-h, --help` | — | 帮助 |
REST 接口(界面的一键操作全走结构化接口):
| 分组 | 接口 |
| ---- | ---- |
| 探活(无需登录) | `GET /api/health`、`GET /api/status` |
| 会话 | `POST /api/login`、`POST /api/logout`、`GET /api/session` |
| 设置 | `GET`/`PUT /api/settings`、`GET`/`PUT /api/ui-settings` |
| 库 | `GET`/`POST /api/databases`、`DELETE /api/databases/:name` |
| 表 | `GET`/`POST /api/tables`、`GET`/`DELETE /api/tables/:t` |
| 行 | `GET`/`POST /api/tables/:t/rows`、`PATCH`/`DELETE /api/tables/:t/rows/:id` |
| 索引与列 | `POST /api/tables/:t/indexes`、`DELETE /api/tables/:t/indexes/:col`、`DELETE /api/tables/:t/columns/:col` |
| 演示数据 | `POST /api/demo-data` |
| SQL 控制台 | `POST /api/query`(`CREATE USER` / `CREATE ROLE` / `GRANT` 也在这里跑) |
| 角色 | `GET`/`POST /api/roles`、`DELETE /api/roles/:name`、`POST`/`DELETE /api/roles/:name/grants`、`POST`/`DELETE /api/roles/:name/members[/:user]` |
除探活、登录和首页(`GET /`、`GET /static/:file`)外都要带会话 Cookie。选库用 `X-ChuSQL-Database` 头:
**不带这个头就是"没选库"**,此时只有限定名语句(`db.table`)能跑,裸表名会得到 400 `no_database`;
`GET /api/databases` 和 `POST`/`DELETE /api/databases/:name` 不需要选库。普通身份碰 `system` 库一律 403。
+112
View File
@@ -0,0 +1,112 @@
# 配置选项
## 文件在哪
整条链路(存储进程 / Web / 命令行)共用一份 `chusql.toml`,位置固定,**没有环境变量可以覆盖**:
| 平台 | 路径 |
| ------------ | ---- |
| Windows | `%APPDATA%\ChuSQL\chusql.toml`(`APPDATA` 没设时退到相对路径 `ChuSQL\chusql.toml`) |
| Linux / macOS | `$XDG_CONFIG_HOME/ChuSQL/chusql.toml`,没设就是 `~/.config/ChuSQL/chusql.toml`(`HOME` 也没有才退相对路径 `ChuSQL/chusql.toml`) |
安装脚本就是把 [`scripts/chusql.toml`](../scripts/chusql.toml) 这份模板写到上面的位置,并把安装时给的
`user` / `password` / `data_dir` 填进去。想临时读另一份文件,`chusql-storage`、`chusql-web`、`csql`
都认 `--config <path>`(启动器 `csql-web` 没有选项,只读固定路径)。
优先级:**命令行选项 > 配置文件 > 内置默认**,也就是配置文件写什么,命令行随时能盖掉
(选项表见 [commands.md](commands.md))。
## 分区归属
| 分区 | 谁读 |
| ---- | ---- |
| `[page]` `[btree]` `[buffer]` `[storage]` `[server]` `[log]` | 存储进程 `chusql-storage` |
| `[web]` | Web 服务 `chusql-web` 与命令行 `csql`(账号、会话、限流、分页上限、静态目录、存储进程路径) |
端点与数据目录只有一份配置:前端读它来决定怎么连,存储进程读它来监听与落盘。
## 存储进程的分区
| 键 | 默认 | 说明 |
| -- | ---- | ---- |
| `[page] size` | `4096` | 页大小(字节) |
| `[btree] order` | `4` | B+ 树阶 |
| `[buffer] pool_size` | `1024` | 缓冲池页数 |
| `[storage] data_dir` | Windows `%LOCALAPPDATA%\ChuSQL\data`,Linux / macOS `${XDG_DATA_HOME:-~/.local/share}/chusql/data` | 数据落哪(模板里那行是安装时替换的占位) |
| `[server] pipe_name` | `chusql-joint` | 端点名(见下) |
| `[log] level` | `info` | 日志级别 |
数据目录跟着平台惯例走,跟安装脚本装的位置是同一处(Windows 装到 `%LOCALAPPDATA%\ChuSQL`、Unix 装到
`~/.local/share/chusql`,数据放在它下面的 `data/`);`LOCALAPPDATA`/`XDG_DATA_HOME`/`HOME` 都没有时才退相对路径。
要固定就写绝对路径。
存储进程只认一个命令行开关:`--config <path>`(`--help` 看帮助)。
## `[web]` 分区
| 键 | 命令行(`chusql-web`) | 默认 | 说明 |
| -- | ---------------------- | ---- | ---- |
| `host` | `--host` | `127.0.0.1` | 监听地址 |
| `port` | `--port` | `7777` | 监听端口 |
| `static_dir` | `--static` | `static` | 静态资源目录(候选:给定值、`static`、`chusql-web/static`、`../chusql-web/static`、`../static`,取第一个存在的) |
| `user` | `--user` | 配置文件缺失时 `root` | 管理员账号名 |
| `password` | — | 文件里**没有**这一项时用内置演示口令 `root` / `chusql` | 管理员口令(明文,启动时哈希;见「口令与安全」) |
| `storage_server` | `--storage` | 空 | 存储进程可执行文件;留空=存储已在别处运行,只按 `[server] pipe_name` 去连 |
| `cookie_secure` | `--cookie-secure` | `false` | 给会话 Cookie 加 `Secure`(HTTPS 部署时开) |
| `body_limit` | `--body-limit` | `65536` | 请求体上限(字节) |
| `session_idle` | `--session-idle` | `28800` | 会话空闲超时(秒) |
| `session_max` | `--session-max` | `86400` | 会话最大存活(秒) |
| `login_max_attempts` | `--login-max-attempts` | `5` | 连续失败几次后限流 |
| `login_window` | `--login-window` | `300` | 限流窗口(秒) |
| `rows_per_page` | `--page-size` | `25` | 默认每页行数 |
| `max_page_size` | `--max-page-size` | `500` | 每页行数上限 |
| `max_rows` | `--max-rows` | `1000` | 单次查询返回行数上限 |
| `max_sql_length` | `--max-sql-length` | `20000` | SQL 字符数上限 |
| `seed` | `--seed` | `false` | 库为空时灌演示数据 |
| `password_min_length` | — | `12` | 普通账号口令最短长度(允许 8–256) |
| `password_classes` | — | `2` | 口令至少包含几类字符(允许 1–4:小写/大写/数字/符号) |
### 键名两种写法都认
模板 `scripts/chusql.toml` 用下划线,Web 设置页写的是连字符(规范形式)。两种写法同时出现时**连字符优先**:
[web]
rows_per_page = 25 # 模板写法
rows-per-page = 50 # 设置页写法,生效
对应关系:`static_dir`→`static-dir`、`session_idle`→`session-idle`、`session_max`→`session-max`、
`login_max_attempts`→`login-max-attempts`、`login_window`→`login-window`、`body_limit`→`body-limit`、
`rows_per_page`→`rows-per-page`、`max_page_size`→`max-page-size`、`max_rows`→`max-rows`、
`max_sql_length`→`max-sql-length`、`storage_server`→`storage-server`、
`password_min_length`→`password-min-length`、`password_classes`→`password-classes`。
`host`、`port`、`user`、`password`、`seed` 只有一种写法。
## 端点(`pipe_name`)
端点只有 `pipe_name` 一个配置,两个平台各一条规则:
| 平台 | 实际地址 |
| ---- | -------- |
| Windows | `\\.\pipe\<pipe_name>`(具名管道) |
| Linux / macOS | `<socket_dir>/<pipe_name>.sock`(文件系统套接字) |
`socket_dir` 按 `$XDG_RUNTIME_DIR` → `$TMPDIR` → `/tmp` 依次取。**前端和存储进程必须在同一套环境变量
下启动**,否则两边算出来的路径不一样。Unix 套接字路径上限约 100 字节,`$XDG_RUNTIME_DIR` 太长时会退到
`/tmp`;上一次崩溃残留的 `.sock` 会被下次启动清掉,若还有进程在听同一个端点,启动会报
`another storage server already listens on ...`。
## 口令与安全
- `password` 给了明文 → 启动时哈希;**显式留空**(`password = ""`)= 只允许管理员免密登录,普通账号一律拒绝登录;
- **整个文件里没有 `password` 这一项** → 回落到内置演示口令 `root` / `chusql`(仅用于本机试用,正式部署请写死);
- 普通账号由管理员在 SQL 控制台用 `CREATE USER` / `ALTER USER` / `DROP USER` 管理,口令受
`password_min_length` / `password_classes` 约束;
- 生产部署建议:`host = 127.0.0.1`(或放在反向代理后)、`cookie_secure = true`、给管理员设口令,
并且别把数据目录放在共享盘上。
## 改配置的两种途径
1. 直接编辑 `chusql.toml`(新值在下次启动生效);
2. Web 设置页(`/api/settings`)按分区把改动写回同一份文件——它会写成连字符形式。
每一项都带注释的模板在 [`scripts/chusql.toml`](../scripts/chusql.toml)。
+110
View File
@@ -0,0 +1,110 @@
# 安装与卸载
发行包里的程序是编好的:**装的人不需要 GHC,也不需要 Rust**。没有对应平台的发行包、或者要改代码时,
走「从源码安装」。
## 三种安装方式
| 方式 | 适用 | 命令 |
| -------- | -------------------------- | -------------------------------------------------------- |
| 在线安装 | 有网络,装最新发行版 | `curl -fsSL .../scripts/install.sh \| sh -s -- --component web` |
| 包内安装 | 手里已有归档(离线、内网) | 解压后在包根跑 `./install.sh --component web` |
| 源码安装 | 没有对应平台资源,或要改代码 | `./install.sh --component web --from-source` |
`--component web` 装 Web 管理端,`--component cli` 装命令行客户端 `csql`;两种都会带上存储进程
`chusql-storage`,因为它是后端。
## 一、发行包
归档由项目在打 tag 时按平台构建上传,名字是 `<component>-<os>-<arch>`,并附 `.sha256`:
| 平台 | 资源名 |
| ------------ | ------------------------------------------------------------------------- |
| Linux x86_64 | `chusql-web-linux-x86_64.tar.gz`、`chusql-cli-linux-x86_64.tar.gz` |
| Windows x86_64 | `chusql-web-windows-x86_64.zip`、`chusql-cli-windows-x86_64.zip` |
| macOS | `chusql-web-macos-x86_64.tar.gz`、`chusql-web-macos-arm64.tar.gz`(cli 同理) |
### 在线安装
一行命令:脚本自己按 `uname` 挑资源、校验 sha256、解包、释放、写配置、加 PATH,最后清掉临时包:
curl -fsSL https://raw.githubusercontent.com/TheBadRoger/ChuSQL/main/scripts/install.sh \
| sh -s -- --component web
仓库与版本可以改:
sh -s -- --component cli --repo OWNER/NAME --version v0.3.0
### 指定归档
不碰网络下载逻辑,直接指一个归档(本地路径、`file://` 或任意 URL):
./install.sh --component web --url dist/chusql-web-linux-x86_64.tar.gz
./install.sh --component cli --url https://example.com/chusql-cli-linux-x86_64.tar.gz
### 包内安装
解压发行包后在包根目录直接跑安装脚本,就是最常见的本地安装:
./install.sh --component web --user root --password '...' # Linux / macOS
./install.ps1 -Component web -RootUser root -RootPassword '...' # Windows
Windows 的 `install.ps1` **只支持包内安装**(没有在线 / 源码模式);要在线装就先手动下载归档。
## 二、安装选项
| `install.sh` | `install.ps1` | 默认 | 说明 |
| ----------------------- | ---------------- | --------------- | ---- |
| `--component web\|cli` | `-Component` | 必填 | 装哪个前端 |
| `--install-dir DIR` | `-InstallDir` | Linux/macOS `$HOME/.local/share/chusql`;Windows `%LOCALAPPDATA%\ChuSQL` | 程序装到哪 |
| `--data-dir DIR` | `-DataDir` | `<install-dir>/data` | 数据落哪 |
| `--user NAME` | `-RootUser` | `root` | 管理员账号名 |
| `--password PW` | `-RootPassword` | 空 | 管理员口令;留空=只允许管理员免密登录 |
| `--keep-package` | `-KeepPackage` | 否 | 装完不删安装包 |
| `--url URL\|PATH` | — | — | 从这个归档装 |
| `--repo OWNER/NAME` | — | `TheBadRoger/ChuSQL` | 从哪个仓库取发行包 |
| `--version TAG` | — | `latest` | 下载模式是 release tag,源码模式是 git ref |
| `--from-source` | — | — | 从源码编译安装 |
| `--source-dir DIR` | — | — | 用本地 checkout 编译,不克隆 |
## 三、从源码安装
需要 `git` + `cargo` + `stack` + `ghc`;Linux 上还要 zlib 开发头(`apt-get install zlib1g-dev`):
./install.sh --component web --from-source # 克隆仓库再编
./install.sh --component web --from-source --source-dir ../ChuSQL # 用本地 checkout
编完之后的释放、写配置、加 PATH 与包内安装完全相同,启动方式也一样。
## 四、装完是什么样
以 Linux、`--component web`、默认目录为例:
| 位置 | 内容 |
| ---- | ---- |
| `~/.local/share/chusql/bin/` | `chusql-storage`、`chusql-web` |
| `~/.local/share/chusql/static/` | Web 前端静态资源 |
| `~/.local/share/chusql/csql-web`、`csql-web.sh` | 启动器与命令入口(`cli` 组件则是 `csql`) |
| `~/.local/share/chusql/init.sql` | 初始化脚本 |
| `~/.local/share/chusql/logs/` | 日志 |
| `~/.local/share/chusql/data/` | 数据目录(Windows 是 `%LOCALAPPDATA%\ChuSQL\data`;可在 `[storage] data_dir` 改) |
| `~/.config/ChuSQL/chusql.toml` | 全局配置(Windows:`%APPDATA%\ChuSQL\chusql.toml`) |
| `~/.profile` | 追加一段 `# ChuSQL` 标记 + `PATH` 输出(Windows 改的是用户级 PATH) |
装完开新终端:
csql-web # 起 Web 前端,默认 http://127.0.0.1:7777
csql # 进命令行
口令留空时只有管理员能进。账号与权限见 [commands.md](commands.md),配置项见 [config.md](config.md)。
## 五、卸载
没有卸载脚本,手工三步(位置按上面的表):
rm -rf ~/.local/share/chusql # 程序与数据(数据另存过就只删程序目录)
rm -f ~/.config/ChuSQL/chusql.toml # 全局配置
# 再编辑 ~/.profile,删掉 "# ChuSQL" 那三行
Windows:删 `%LOCALAPPDATA%\ChuSQL` 与 `%APPDATA%\ChuSQL\chusql.toml`,再到「环境变量」里把安装目录
从用户 PATH 移除。