SQL_DRIVER_GUIDE.md 5.7 KB

database/sql 驱动(vrtxsql)

DB/driver 包实现了 Go 标准库 database/sql/driver 接口,让任意基于 database/sql 的工具与 ORM(xorm、sqlx、自研 ORM 等)直接对接 VRTX 引擎, 无需引入任何第三方依赖(解析器为内置的 ORM 子集翻译器)。

import (
	"database/sql"
	_ "git.ycl.pub/yl32940/TsDB2/DB/driver" // 注册 "vrtx" 驱动
)

db, err := sql.Open("vrtx", "/path/to/data.db") // DSN = 数据库文件路径
if err != nil { ... }
defer db.Close()

db.SetMaxOpenConns(1) // 引擎单写者模型: 1 路连接即可 (见下文"连接与并发")

同一进程内相同路径的多个 sql.DB 共享同一个引擎实例(注册表 + 引用计数), 不会出现一个库被打开成两个实例的撕裂。

完整可运行示例见 demo/sql_driver。


支持的语句

SELECT

SELECT * FROM t
SELECT 列1, 列2 FROM t                    -- 投影 (AS 别名可写, 展示以表列名为准)
SELECT ... FROM t WHERE 条件
SELECT ... FROM t WHERE 条件 ORDER BY 列 [ASC|DESC], ... LIMIT n [OFFSET m]
SELECT COUNT(*) | COUNT(列) | SUM(列) | MIN(列) | MAX(列) | AVG(列) FROM t [WHERE ...]

WHERE 条件族(? 为参数占位符,字面量同样可用):

语法 说明
= != <> < <= > >= 比较;NULL 参与比较恒不成立(SQL 语义)
AND OR NOT 逻辑组合,支持 ( ... ) 分组
列 IN (v1, v2, ...) / NOT IN (...) 走索引展开定位,不退化全表扫描
列 IS NULL / 列 IS NOT NULL 按行内 NULL 位图判定
列 LIKE '前缀%' / NOT LIKE 通配符 % _

INSERT

INSERT INTO t VALUES (...)
INSERT INTO t (列...) VALUES (...), (...)    -- 多行
INSERT INTO t (列...) VALUES (?, ?)          -- 参数占位
  • 提供了主键列的整数值 → 该行就使用该主键号(LastInsertId 返回它); 未提供 → 引擎自增分配。
  • 省略的列自动置 NULL:可空列写入 NULL 位;非空列缺值报错(与 SQL 一致)。

UPDATE / DELETE

UPDATE t SET 列=值, ... [WHERE 条件]
DELETE FROM t [WHERE 条件]

WHERE 定位到行号后逐行生效,RowsAffected 真实。省略 WHERE = 作用于全表。

DDL

CREATE TABLE [IF NOT EXISTS] t (
	列  类型 [(参数)]  [NULL|NOT NULL] [UNIQUE] [PRIMARY KEY] [DEFAULT NULL] ...,
	[PRIMARY KEY (列)],
	[KEY|INDEX 名 (列)],
	[UNIQUE KEY 名 (列)]
)
CREATE [UNIQUE] INDEX 名 ON t (列)
DROP TABLE [IF EXISTS] t

列类型映射:

SQL 类型 引擎类型 备注
BIGINT (+UNSIGNED) Int64 / Uint64 主键列必须是整数类型
INT/INTEGER SMALLINT TINYINT (+UNSIGNED) Int32/16/8 / Uint*
DOUBLE FLOAT Float64/32
BOOL BOOLEAN Bool
VARCHAR(n) CHAR(n) String(定长档) n ≤ 2048;超出请用 TEXT
TEXT 动态列 不可建索引
BLOB Blob 列 行内 8B 引用,SELECT 出见限制
DECIMAL(p,s) Decimal s 落列级参数
DATETIME TIMESTAMP Uint64 约定:毫秒时间戳
UUID UUID

列级 AUTO_INCREMENT / COMMENT '...' 可写(被忽略);DEFAULT 仅支持 DEFAULT NULL,其它默认值报错(避免静默错配)。


不支持的语句(明确报错,不静默)

类别 内容
多表 JOIN(任何形式)
嵌套 子查询、INSERT ... SELECT
分组 GROUP BY、HAVING、DISTINCT
函数 WHERE/SELECT 中的任意函数表达式(UPPER/CASE WHEN 等)
索引 多列(复合)索引、复合主键 PRIMARY KEY (a, b)
变更 ALTER TABLE 全部
语法糖 BETWEEN(用 >= AND <= 代替)、ON DUPLICATE KEY UPDATE、REPLACE INTO
DDL 附加 DEFAULT 非 NULL 值、VIEW/TRIGGER/过程
其它 事务隔离级别设置、LIMIT ? 参数化(LIMIT 只接受字面量)

语义与类型约定

  • NULL:省略列 = NULL;NULL 参与任何比较恒不成立;聚合的 AVG 分母 是"该列非 NULL 的行数";COUNT(*) 数全行。字符串结果统一以 []byte 返回 (Scan 到 string / []byte 均可),NULL 扫描为 nil。
  • 时间:time.Time 参数按毫秒时间戳存入 DATETIME 列;读出走引擎类型。
  • 事务:db.Begin() / tx.Commit() / tx.Rollback(),语义即引擎的 BeginTransaction;BEGIN 会把此前自动提交挂起的修改先落盘(SQL 标准语义: BEGIN 是"之前工作已提交"的边界)。事务内的 DDL 报错(引擎 DDL 隐式提交语义)。
  • 错误传播:唯一索引冲突、非空约束、语法错误、不支持的语句——全部以 error 返回,错误信息含具体列/索引/语法点。

连接与并发

引擎是单写者模型。驱动内所有操作经一把全局锁串行化:同一时刻只有一个 操作在跑,事务期间其它连接的操作排队等待(拥有事务的连接自身不会被卡死)。 因此 SetMaxOpenConns(1) 是最优配置;不设也能正确运行,只是并发请求会排队。

已知限制

  • SELECT 结果集全量物化进内存(大结果集占用内存,后续可换流式)。
  • BLOB 列不支持 SELECT 出(行内只有引用),返回明确错误;请用引擎 Blob API 读取。
  • 时序表(行存储为时序索引)同样可经驱动写入:主键列声明 DATETIME 且按时间非递减写入即可。

测试与演示

  • 驱动测试:go test ./DB/driver/(CRUD/查询全链路、事务、不支持语法、 共享引擎共 4 组)。
  • 演示:cd demo/sql_driver && go run main.go —— M1/M2/M3 全特性走查。