OctoSQL 0.13.0 常用 CLI 命令详解

OctoSQL 0.13.0 CLI 全实测:单查询进程无交互 REPL、四类表源与 stdin 管道、五种输出格式、--describe/--explain/--profile 三件套、docs/plugins 内置系统表、插件管理与 shell 补全,附三源 JOIN 实战与 7 条排障实录。

OctoSQLOctoSQLCLI工具SQL命令行2026/11/03

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`"`
无表头 CSVoctosql "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 配置参数详解》。