OctoSQL 0.13.0 常用 CLI 命令详解
OctoSQL 0.13.0 CLI 全实测:单查询进程无交互 REPL、四类表源与 stdin 管道、五种输出格式、--describe/--explain/--profile 三件套、docs/plugins 内置系统表、插件管理与 shell 补全,附三源 JOIN 实战与 7 条排障实录。
OctoSQL 0.13.0 常用 CLI 命令详解
OctoSQL 的 CLI 面比大多数同类工具都小:一条查询就是一个进程,没有守护进程、没有会话状态。本文把 v0.13.0 的全部命令与高频用法逐一实测讲透:查询执行、五种输出格式、--describe/--explain/--profile 三件套、docs/plugins 两套内置系统表、插件管理与 shell 补全,并给出跨源 JOIN 实战与一组排障实录。环境:app01(Ubuntu 22.04)+ db01(PostgreSQL 16),数据目录 /opt/datasets,配置见《OctoSQL 0.13.0 配置参数详解》。
一、命令总览与"交互模式"澄清
octosql --help 实测输出(列描述文字与报错时的 usage 完全一致):
Usage:
octosql <query> [flags]
octosql [command]
Examples:
octosql "SELECT * FROM myfile.json"
octosql "SELECT * FROM mydir/myfile.csv"
octosql "SELECT * FROM plugins.plugins"
Available Commands:
completion Generate the autocompletion script for the specified shell
help Help about any command
plugin
Flags:
--describe Describe query output schema.
--explain int Describe query output schema.
-h, --help help for octosql
--optimize Whether OctoSQL should optimize the query. (default true)
-o, --output string Output format to use. Available options are live_table, batch_table, csv, json and stream_native. (default "live_table")
--profile string Enable profiling of the given type: cpu, memory, trace.
-v, --version version for octosql
Use "octosql [command] --help" for more information about a command.
先澄清最大的误区:网上教程里的"交互模式 / REPL、/connect、/tables 元命令"在 v0.13.0 不存在。实测不带参数运行只打印 usage 帮助并报错退出:
root@app01:/opt/datasets# octosql
Usage:
octosql <query> [flags]
...(同上完整 usage)...
Error: accepts 1 arg(s), received 0
root@app01:/opt/datasets# echo $?
1
一切操作都通过"一条命令一条查询"完成;所谓"元命令"的等价物是内置的 docs 与 plugins 系统数据库(见第四节)。另一个通用行为:任何查询失败都会先打印完整 usage 块再打 Error: 行,下文排障实录为省篇幅只摘 Error: 行。
二、查询执行
2.1 基本形式
查询字符串作为第一个位置参数,表写在 FROM 里:
root@app01:/opt/datasets# octosql "SELECT * FROM employees.csv"
+------+--------------+---------+--------+
| id | name | dept_id | salary |
+------+--------------+---------+--------+
| 1001 | 'Alice Wang' | 1 | 18500 |
| 1002 | 'Bob Chen' | 1 | 16200 |
| 1003 | 'Carol Li' | 2 | 21000 |
| 1004 | 'Dave Zhang' | 2 | 19800 |
| 1005 | 'Eve Liu' | 3 | 15600 |
| 1006 | 'Frank Zhao' | 3 | 17400 |
| 1007 | 'Grace Sun' | 1 | 22300 |
+------+--------------+---------+--------+
表源四类(语法细节见配置详解第二、三节):本地文件(employees.csv、`json.departments.jsonl`)、命名数据库(hrdb.bonus)、stdin 虚拟表(stdin.json、stdin.lines)、内置表值函数(range(...))。
2.2 stdin 管道
root@app01:/opt/datasets# echo '{"hello": "world"}' | octosql "SELECT * FROM stdin.json"
+---------+
| hello |
+---------+
| 'world' |
+---------+
root@app01:/opt/datasets# seq 100 | octosql "SELECT SUM(int(text)) AS total FROM stdin.lines"
+-------+
| total |
+-------+
| 5050 |
+-------+
stdin.lines 固定两列,实测 --describe:number(Int,行号)+ text(String)。
2.3 退出码
成功为 0,任何错误(文件不存在、表不存在、语法错误)统一为 1,可直接用于 shell 脚本判断:
root@app01:/opt/datasets# octosql "SELECT * FROM nosuch.csv" 2>&1 | tail -1
Error: typecheck error: couldn't create datasource: couldn't open local file: couldn't open file: open nosuch.csv: no such file or directory
root@app01:/opt/datasets# echo $?
1
三、输出格式:-o / --output
五种取值,默认 live_table(边算边打)。实测对照:
csv——机器可读,适合重定向落盘(注意字符串不带引号):
root@app01:/opt/datasets# octosql "SELECT name, salary FROM employees.csv WHERE salary > 20000" -o csv
name,salary
Carol Li,21000
Grace Sun,22300
json——每行一个 JSON 对象(NDJSON 风格):
root@app01:/opt/datasets# octosql "SELECT name, salary FROM employees.csv WHERE salary > 20000" -o json
{"name":"Carol Li","salary":21000}
{"name":"Grace Sun","salary":22300}
batch_table——攒齐再打,与 live_table 只差刷新时机:
root@app01:/opt/datasets# octosql "SELECT COUNT(*) AS n FROM employees.csv" -o batch_table
+---+
| n |
+---+
| 7 |
+---+
stream_native——内部流记录格式(事件时间 + 记录体),用于调试流式语义,日常用得少:
root@app01:/opt/datasets# octosql "SELECT name FROM employees.csv LIMIT 2" -o stream_native
{+0001-01-01T00:00:00Z| 'Alice Wang' |}
{+0001-01-01T00:00:00Z| 'Bob Chen' |}
落盘套路就是重定向:
root@app01:/opt/datasets# octosql "SELECT * FROM hrdb.bonus" -o csv > /opt/datasets/bonus_export.csv
四、自省命令:--describe 与 docs/plugins 系统表
4.1 --describe:先看 schema 再写 JOIN
任何查询加 --describe 只输出结果集 schema(列名/类型/时间列)不执行取数(列按字母序排列):
root@app01:/opt/datasets# octosql "SELECT * FROM employees.csv" --describe
+-----------+----------+------------+
| name | type | time_field |
+-----------+----------+------------+
| 'dept_id' | 'Int' | false |
| 'id' | 'Int' | false |
| 'name' | 'String' | false |
| 'salary' | 'Int' | false |
+-----------+----------+------------+
root@app01:/opt/datasets# octosql "SELECT * FROM hrdb.bonus" --describe
+-----------+-----------------+------------+
| name | type | time_field |
+-----------+-----------------+------------+
| 'bonus' | 'NULL | Float' | false |
| 'emp_id' | 'NULL | Int' | false |
| 'quarter' | 'NULL | String' | false |
+-----------+-----------------+------------+
注意 postgres 侧可空列显示为联合类型 NULL | Int——写查询前先 describe 一遍,能提前发现 Int 对 Float 这类会静默吃掉 JOIN 的类型差。
4.2 docs 数据库:函数清单内置在程序里
root@app01:/opt/datasets# octosql "SELECT name, description FROM docs.functions LIMIT 5" -o batch_table
+---------+--------------------------+
| name | description |
+---------+--------------------------+
| '[]' | 'Implements the indexing |
| | operator: list[index]' |
| 'abs' | 'Returns absolute value |
| | of argument.' |
| 'ceil' | 'Returns ceiling of |
| | argument.' |
| 'float' | 'Converts the argument |
| | to an float.' |
| 'floor' | 'Returns floor of |
| | argument.' |
+---------+--------------------------+
聚合函数全集(实测 10 个):
root@app01:/opt/datasets# octosql "SELECT name FROM docs.aggregates" -o batch_table
+----------------------+
| name |
+----------------------+
| 'array_agg' |
| 'array_agg_distinct' |
| 'avg' |
| 'avg_distinct' |
| 'count' |
| 'count_distinct' |
| 'max' |
| 'min' |
| 'sum' |
| 'sum_distinct' |
+----------------------+
docs.function_signatures / docs.aggregate_signatures 还能查参数名与类型(本文 poll 排障就靠它,见第十节实录 5)。
4.3 plugins 数据库:插件状态 SQL 化
root@app01:/opt/datasets# octosql "SELECT * FROM plugins.installed_plugins" -o batch_table
+---------------+-----------+
| name | repo_slug |
+---------------+-----------+
| 'postgres' | 'core' |
| 'random_data' | 'core' |
+---------------+-----------+
可装全集见配置详解 3.1(plugins.available_plugins),版本清单查 plugins.available_versions。
五、执行计划:--explain 与 --optimize
--explain 1 输出查询计划 DOT 图并渲染成 PNG(依赖 graphviz 的 dot,未装时报 Error: couldn't render graph: exec: "dot": executable file not found in $PATH);--explain 2 在节点上附加列与类型信息。
无桌面环境的服务器实测:渲染成功但打开失败,PNG 仍会生成在 /tmp,取回本地看即可:
root@app01:/opt/datasets# octosql "SELECT i FROM range(start=>1,end=>2) r" --explain 1 2>&1 | tail -1
Error: couldn't open graph: exec: "xdg-open": executable file not found in $PATH
root@app01:/opt/datasets# ls /tmp/octosql-explain-*.png
/tmp/octosql-explain-4031004614.png
看什么:以 LOOKUP JOIN 为例,--explain 1 渲染的计划图里,employees.csv 源节点标注了 filter predicate(WHERE e.id = 1001 被下推到文件扫描侧),hrdb.bonus 源节点带 predicate 标签(JOIN 键条件作为查询参数下推给 db01)——这就是 LOOKUP JOIN 把"大表×维表"变成"逐行查库"的实现证据。
--optimize(默认 true)控制是否跑优化器;对简单查询实测开/关计划图无肉眼差异,主要用途是排查可疑的下推行为时做二分对照。
六、性能剖析:--profile
root@app01:/opt/datasets# octosql "SELECT COUNT(*) AS n FROM employees.csv" --profile cpu
2026/11/03 04:02:54 profile: cpu profiling enabled, cpu.pprof
+---+
| n |
+---+
| 7 |
+---+
root@app01:/opt/datasets# ls -la cpu.pprof
-rw-r--r-- 1 root root 212 Nov 3 04:02 cpu.pprof
--profile cpu|memory|trace 把 Go pprof 数据写到当前目录(cpu.pprof 等),分析需要 Go 工具链:go tool pprof cpu.pprof。大文件 JOIN 变慢时,先用它定位是解码瓶颈还是 shuffle 瓶颈。
七、插件管理命令
Usage:
octosql plugin [command]
Available Commands:
install
repository
安装(@ 指定版本,默认装仓库最新版):
root@app01:/opt/datasets# https_proxy=http://192.168.1.72:7897 octosql plugin install postgres
Downloading core/postgres@0.3.0...
卸载:没有 uninstall 子命令,手动 rm -rf ~/.octosql/plugins 即可(实测删目录后任何查询报插件未安装,重装恢复)。
第三方仓库(只有 add 一个子命令):
Usage:
octosql plugin repository add [repository name, in <owner>/<name> format] [ref]
八、Shell 补全
root@app01:~# octosql completion bash > /etc/bash_completion.d/octosql
root@app01:~# wc -l /etc/bash_completion.d/octosql
288 /etc/bash_completion.d/octosql
root@app01:~# head -1 /etc/bash_completion.d/octosql
# bash completion V2 for octosql -*- shell-script -*-
支持 bash|zsh|fish|powershell 四种 shell,实测 bash 输出为标准 cobra 补全脚本。
九、跨源 JOIN 实战
本文主菜:app01 上的 employees.csv + departments.jsonl 与 db01 上的 bonus 表三源关联,一条 SQL:
root@app01:/opt/datasets# octosql "SELECT e.name, d.name AS dept, d.location, b.quarter, b.bonus FROM employees.csv e JOIN \`json.departments.jsonl\` d ON e.dept_id = int(d.id) JOIN hrdb.bonus b ON b.emp_id = e.id ORDER BY e.name, b.quarter"
+--------------+---------------+------------+----------+-------+
| name | dept | location | quarter | bonus |
+--------------+---------------+------------+----------+-------+
| 'Alice Wang' | 'Engineering' | 'Shanghai' | '2026Q3' | 3000 |
| 'Alice Wang' | 'Engineering' | 'Shanghai' | '2026Q4' | 3500 |
| 'Bob Chen' | 'Engineering' | 'Shanghai' | '2026Q3' | 2500 |
| 'Carol Li' | 'Finance' | 'Beijing' | '2026Q3' | 4200 |
| 'Carol Li' | 'Finance' | 'Beijing' | '2026Q4' | 4600 |
| 'Dave Zhang' | 'Finance' | 'Beijing' | '2026Q3' | 3800 |
| 'Eve Liu' | 'Operations' | 'Shenzhen' | '2026Q3' | 1500 |
| 'Grace Sun' | 'Engineering' | 'Shanghai' | '2026Q4' | 5100 |
+--------------+---------------+------------+----------+-------+
要点复盘:JSONL 用反引号记法;int(d.id) 对齐 Float/Int;hrdb.bonus 来自 octosql.yml;ORDER BY 用输出列别名。
LOOKUP JOIN(员工表做驱动流、bonus 做维表逐行下推查库,配 --explain 1 可看下推):
root@app01:/opt/datasets# octosql "SELECT e.name, b.bonus FROM employees.csv e LOOKUP JOIN hrdb.bonus b ON b.emp_id = e.id WHERE e.id = 1001"
+--------------+-------+
| name | bonus |
+--------------+-------+
| 'Alice Wang' | 3000 |
| 'Alice Wang' | 3500 |
+--------------+-------+
分组聚合 + HAVING(跨文件聚合照常工作):
root@app01:/opt/datasets# octosql "SELECT d.name AS dept, COUNT(*) AS n, MAX(e.salary) AS max_sal FROM employees.csv e JOIN \`json.departments.jsonl\` d ON e.dept_id = int(d.id) GROUP BY d.name HAVING COUNT(*) >= 2 ORDER BY dept"
+---------------+---+---------+
| dept | n | max_sal |
+---------------+---+---------+
| 'Engineering' | 3 | 22300 |
| 'Finance' | 2 | 21000 |
| 'Operations' | 2 | 17400 |
+---------------+---+---------+
嵌套 JSON 字段访问(-> 取对象字段、[] 取数组下标;列名带 jsonl. 前缀需反引号):
root@app01:/opt/datasets# octosql "SELECT \`jsonl.info\`->name AS uname, \`jsonl.info\`->age AS uage, \`jsonl.tags\`[0] AS t0 FROM \`json.obj.jsonl\`"
+-------+------+-----+
| uname | uage | t0 |
+-------+------+-----+
| 'Tom' | 30 | 'a' |
+-------+------+-----+
任意文本按行读取(lines. 记法;列名 txt.number/txt.text,起别名后可裸用后缀):
root@app01:/opt/datasets# octosql "SELECT l.text FROM \`lines.notes.txt\` l"
+---------+
| text |
+---------+
| 'alpha' |
| 'beta' |
| 'gamma' |
+---------+
表值函数 range(造数/补日历常用,命名参数用 =>):
root@app01:/opt/datasets# octosql "SELECT i FROM range(start=>1, end=>6) r"
+---+
| i |
+---+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
+---+
十、排障实录
(octosql 报错时会先打完整 usage 块,以下只摘 Error: 行原文。)
实录 1:JSON 数组文件读不了。
Error: typecheck error: couldn't create datasource: couldn't parse json: cannot parse JSON: cannot parse array: missing ']'; unparsed tail: ""。JSON 源只认 JSON Lines,jq -c '.[]' 转换后再读(配置详解 2.2)。
实录 2:JOIN 不报错但结果全空。
ON e.dept_id = d.id 实测返回 0 行——CSV 的 Int 与 JSON 的 Float 比较不成立。describe 两边类型,显式 int()/float()。这是 OctoSQL 最隐蔽的坑。
实录 3::: 类型断言报"非联合类型"。
SELECT d.id::Int ... 报 Error: typecheck error: typecast of non-union type expression 'Float'。:: 只用于联合类型取值(如库里的 NULL | Int 列),纯 Float→Int 用转换函数 int()。
实录 4:三段式表名解析失败。
SELECT * FROM hrdb.public.bonus 报 Error: couldn't parse query: invalid argument syntax error at position 27。模式名走 octosql.yml 的 schema,SQL 只写两段。
实录 5:poll 表值函数三种调用全部失败。
docs.function_signatures 显示签名为 poll(interval, initial_delay, source),但实测:README 的 poll_interval=> 写法报 unknown table valued function;interval=> 与位置参数写法都报 invalid argument syntax error near 'interval'(interval 是保留字,无法作参数名)。v0.13.0 的 poll 实际不可用,流式轮询需求请换方案。
实录 6:.jsonl/.txt 裸写报 no such table。
SELECT * FROM departments.jsonl → Error: typecheck error: couldn't create datasource: no such table: departments.jsonl。非自动识别扩展名必须用反引号记法 `json.departments.jsonl`(配置详解 2.1/2.2)。
实录 7:数据库里的表不存在。
SELECT * FROM hrdb.nosuchtable → Error: ... couldn't get table: table nosuchtable does not exist(插件侧透传,说明连接本身是通的)。
十一、速查表
| 任务 | 命令 |
|---|---|
| 查版本 | octosql --version |
| 查文件 | octosql "SELECT * FROM data.csv" |
| 查特殊扩展名文件 | octosql "SELECT * FROM \json.data.jsonl`"` |
| 无表头 CSV | octosql "SELECT * FROM \csv.raw.csv?header=false`"` |
| 看 schema | 任意查询加 --describe |
| 看执行计划 | 任意查询加 --explain 1(需 graphviz) |
| 导 CSV/JSON | -o csv / -o json + 重定向 |
| 管道进查询 | cmd | octosql "SELECT ... FROM stdin.lines" |
| 函数清单 | octosql "SELECT * FROM docs.functions" |
| 插件状态 | octosql "SELECT * FROM plugins.installed_plugins" |
| 装插件 | octosql plugin install postgres |
| 性能剖析 | --profile cpu → cpu.pprof |
三篇配套:认知与选型看《OctoSQL 0.13.0 介绍与选型指南》,部署看《OctoSQL 0.13.0 安装部署指南》,配置看《OctoSQL 0.13.0 配置参数详解》。