feat: 完成批量插入的SQL生成功能
This commit is contained in:
178
insert_build.go
Normal file
178
insert_build.go
Normal file
@@ -0,0 +1,178 @@
|
||||
package td_builder
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// buildInsertStatementForSuperTable 构建超级表插入语句
|
||||
// @param rows 同一超级表下的数据行
|
||||
// @return 插入语句
|
||||
func buildInsertStatementForSuperTable(rows ...*TableRowMateria) (string, error) {
|
||||
if len(rows) == 0 {
|
||||
return "", fmt.Errorf("no rows provided for super table insert")
|
||||
}
|
||||
|
||||
var sb strings.Builder
|
||||
|
||||
// 格式化标签列和值
|
||||
formattedTagColumns := formatColumns(rows[0].TagColumns...)
|
||||
formattedTagValues := formatRowValues(rows[0].TagValues...)
|
||||
formattedColumns := formatColumns(rows[0].Columns...)
|
||||
|
||||
formattedSuperTableName := formatIdentifier(rows[0].SuperTableName)
|
||||
formattedTableName := formatIdentifier(rows[0].TableName)
|
||||
|
||||
/*
|
||||
insert into `dev_001`
|
||||
using `super_dev` (`dev_id`,`dev_type`) tags ('A001','电表')
|
||||
(`ts`,`aV`,`bV`,`aI`,`bI`) values
|
||||
('2024-09-01T00:00:00+08:00','220','221','20.0','20.1'),
|
||||
('2024-09-02T00:00:00+08:00','220','221','20.0','20.1')
|
||||
*/
|
||||
|
||||
// 构建插入语句头部
|
||||
sb.WriteString(fmt.Sprintf("%s USING %s %s TAGS %s %s VALUES ",
|
||||
formattedTableName, formattedSuperTableName,
|
||||
formattedTagColumns,
|
||||
formattedTagValues,
|
||||
formattedColumns,
|
||||
))
|
||||
|
||||
// 添加每行的值
|
||||
for i, row := range rows {
|
||||
if i > 0 {
|
||||
sb.WriteString(",")
|
||||
}
|
||||
sb.WriteString(formatRowValues(row.Values...))
|
||||
}
|
||||
|
||||
return sb.String(), nil
|
||||
}
|
||||
|
||||
// buildInsertStatementForNormalTable 普通表插入构建
|
||||
// @param data 数据 当前应该是同一个表的
|
||||
// @return 插入语句 表名1 (列名) VALUES (),()
|
||||
func buildInsertStatementForNormalTable(rows ...*TableRowMateria) (string, error) {
|
||||
if len(rows) == 0 {
|
||||
return "", fmt.Errorf("no data provided for normal table insert")
|
||||
}
|
||||
|
||||
var sb strings.Builder
|
||||
formattedColumns := formatColumns(append(rows[0].TagColumns, rows[0].Columns...)...)
|
||||
formattedTableName := formatIdentifier(rows[0].TableName)
|
||||
|
||||
/*
|
||||
insert into `dev_001`
|
||||
(`ts`,`aV`,`bV`,`aI`,`bI`) values
|
||||
('2024-09-01T00:00:00+08:00','220','221','20.0','20.1'),
|
||||
('2024-09-02T00:00:00+08:00','220','221','20.0','20.1')
|
||||
*/
|
||||
|
||||
// 构建插入语句头部
|
||||
sb.WriteString(fmt.Sprintf("%s %s VALUES ", formattedTableName, formattedColumns))
|
||||
|
||||
// 添加每行的值
|
||||
for i, row := range rows {
|
||||
if i > 0 {
|
||||
sb.WriteString(",")
|
||||
}
|
||||
sb.WriteString(formatRowValues(append(row.TagValues, row.Values...)...))
|
||||
}
|
||||
|
||||
return sb.String(), nil
|
||||
}
|
||||
|
||||
// formatRowValues 格式化单行的值并返回格式化后的字符串
|
||||
// @param values 单行的值
|
||||
// @return 格式化后的字符串 ('a',12.3,true,)
|
||||
func formatRowValues(values ...any) string {
|
||||
formattedValues := make([]string, len(values))
|
||||
for i, val := range values {
|
||||
switch v := val.(type) {
|
||||
case sql.NullBool:
|
||||
if v.Valid {
|
||||
formattedValues[i] = fmt.Sprintf("%v", v.Bool)
|
||||
} else {
|
||||
formattedValues[i] = "null"
|
||||
}
|
||||
case sql.NullByte:
|
||||
if v.Valid {
|
||||
formattedValues[i] = fmt.Sprintf("%v", v.Byte)
|
||||
} else {
|
||||
formattedValues[i] = "null"
|
||||
}
|
||||
case sql.NullFloat64:
|
||||
if v.Valid {
|
||||
formattedValues[i] = fmt.Sprintf("%v", v.Float64)
|
||||
} else {
|
||||
formattedValues[i] = "null"
|
||||
}
|
||||
case sql.NullInt64:
|
||||
if v.Valid {
|
||||
formattedValues[i] = fmt.Sprintf("%v", v.Int64)
|
||||
} else {
|
||||
formattedValues[i] = "null"
|
||||
}
|
||||
case sql.NullInt32:
|
||||
if v.Valid {
|
||||
formattedValues[i] = fmt.Sprintf("%v", v.Int32)
|
||||
} else {
|
||||
formattedValues[i] = "null"
|
||||
}
|
||||
case sql.NullInt16:
|
||||
if v.Valid {
|
||||
formattedValues[i] = fmt.Sprintf("%v", v.Int16)
|
||||
} else {
|
||||
formattedValues[i] = "null"
|
||||
}
|
||||
case sql.NullString:
|
||||
if v.Valid {
|
||||
formattedValues[i] = fmt.Sprintf("'%s'", v.String)
|
||||
} else {
|
||||
formattedValues[i] = "null"
|
||||
}
|
||||
case sql.NullTime:
|
||||
if v.Valid {
|
||||
formattedValues[i] = fmt.Sprintf("'%s'", v.Time.Format(time.RFC3339))
|
||||
} else {
|
||||
formattedValues[i] = "null"
|
||||
}
|
||||
case string:
|
||||
formattedValues[i] = fmt.Sprintf("'%s'", v)
|
||||
case rune: // rune 转换为 string
|
||||
formattedValues[i] = fmt.Sprintf("'%s'", string(v))
|
||||
case nil:
|
||||
formattedValues[i] = "null"
|
||||
case time.Time:
|
||||
formattedValues[i] = fmt.Sprintf("'%s'", v.Format("2006-01-02 15:04:05"))
|
||||
default:
|
||||
if reflect.TypeOf(val).Kind() == reflect.Ptr && reflect.ValueOf(val).IsNil() {
|
||||
formattedValues[i] = "null"
|
||||
continue
|
||||
}
|
||||
formattedValues[i] = fmt.Sprintf("%v", val)
|
||||
}
|
||||
}
|
||||
return "(" + strings.Join(formattedValues, ",") + ")"
|
||||
}
|
||||
|
||||
// formatIdentifier 为表名或超级表名添加反引号
|
||||
// @param identifier 表名或超级表名
|
||||
// @return 格式化后的字符串 `tableName`
|
||||
func formatIdentifier(identifier string) string {
|
||||
return fmt.Sprintf("`%s`", identifier)
|
||||
}
|
||||
|
||||
// formatColumns 为列名添加反引号
|
||||
// @param columns 列名
|
||||
func formatColumns(columns ...string) string {
|
||||
formatted := make([]string, len(columns))
|
||||
for i, col := range columns {
|
||||
formatted[i] = fmt.Sprintf("`%s`", col)
|
||||
}
|
||||
return "(" + strings.Join(formatted, ",") + ")"
|
||||
}
|
||||
Reference in New Issue
Block a user