我之前在项目开发中遇到一个痛点,比如我在实现 SQL 解析的若干功能,需要写大量的单元测试,测试中需要指定 SQL 字符串,本着代码与数据分离的思想,这些单测的 SQL 和其它相关的变量数据,应该单独存储在代码外的某个地方。
开发中常见的一些配置文件格式,比如 json、yaml、toml 等等,都是有特定语法规则,而 SQL 字符串中各种可能有的字符都有,容易出现格式问题,比如换行符,单双引号,及其它问题。编写这些配置文件就显得相当繁琐而且易出错。
于是我就产生了一个想法,自己编写一种特殊的配置文件格式,让写 SQL 字符串变得直观、简单。我把我设计的这种简单文件格式称之为:TML,全称为 Test Markup Language。
tml 标记语言
tml 全称 Testing Markup Language,是用于存储单元测试中变量的文本文件。格式简单
结构体定义
目前仅支持以下几种字段数据类型
- int
- string
- []string
- map[string]string
使用 tml 来标记 struct 中的字段。如
type tmlData struct {
Sql string `tml:"sql"`
Deps string `tml:"deps"`
Meta map[string]string `tml:"meta"`
}
按上面定义,遇到 sql 变量,会按字符串提取。meta 变量按字典规则提取。
解析示例
r, err := os.Open(path)
if err != nil {
t.Fatalf("open %s failed, err: %s", path, err)
}
defer r.Close()
d := tml.NewDecoder(r)
var data tmlData
if err = d.Decode(&data); err != nil {
t.Fatalf("parse tml file %s failed, err: %s", path, err)
}
tml 文件语法
变量赋值
行开始,连接两个 @ ,再接着变量名,@@ 前面不能有空白字符
例如
@@ sql
select from
table aaa
表示下面行所有字符串,赋值给 sql 变量
字符串变量会去掉前后空白符。
注释
行开始,连续两个 # 表示注释行。# 前不能有空白字符。
数组变量
只支持字符串数组
数组使用逗号隔开,不考虑数组值当中含有逗号的情况
## 数组示例
@@ arr1
field1, field2, 333
字典变量
只支持 map[string]string 类型。
格式为字典 key + 冒号 + value。
示例
## 字典示例
@@ map1
user: name
pass: word
tml 文件示例
对于定义结构体
struct {
Sql string `tml:"sql"`
Users []string `tml:"users"`
Ages map[string]string `tml:"ages"`
Count int `tml:"count"`
}
相应的 tml 文件内容如下
// 文件开始可以写一些文本,会被忽略
@@ sql
select *
from table a
union join b
## 这是一行注释,注释开头必须是 ## ,# 前不能有空格
@@ users
## 中间还可以有注释
kyle, alice, john
@@ ages
kyle: 22
alice: 23
## 中间还可以有注释
john: 29
@@ count
## comment
7899
另一个我实际使用到的 tml 文件内容:
## 修复匿名字段,这里的 target_table.$1 可以与 meta 中的字段映射上,也就是 $2 会转换成 target_table 的第 2 个字段
@@ sql
INSERT INTO
TABLE target_table
SELECT
col1,
(
SELECT
MAX(col2)
FROM
another_table
WHERE
col1 = source_table.col1
)
FROM
source_table;
@@ dialect
hive
@@ meta
target_table: col1, fixed_col2
@@ bags
1
@@ not_keep_query
1
@@ deps
source_table.col1 -> target_table.col1
another_table.col2 -> target_table.fixed_col2
tml 解析源码
代码量不多,我直接放在了 Github 上: https://gist.github.com/kylege/e4ddaa1c38818083c7244b229adde9cc