/*
* 生成 insert table_name(xxx) value(xxx) on duplicate key update语句
*/
func (impl *SaveOrUpdateTableLoader) generateSaveOrUpdateSqlExt(ctx *core.EtlContext, transResult *vo.TransformResult, incrConfig *vo.IncrementConfig) (*SqlResult, error) {
/*
* 解析transResult中的目标列meta信息。
*/
var loadColumns []*LoadColumn
if transResult.DataType.Kind() == reflect.Map {
columns, err := getColumnMap(transResult, impl.loadColumnConfigMap)
if err != nil {
logrus.Errorf("saveOrUpdateLoad生成sql:从map数据集中解析load字段错误=>%s", err)
return nil, err
}
dbConfig := ds.DbConfig{
Ip: impl.targetLoadConfig.TargetDs.DbIp,
Port: uint32(impl.targetLoadConfig.TargetDs.DbPort),
Account: impl.targetLoadConfig.TargetDs.DbUser,
Password: impl.targetLoadConfig.TargetDs.DbPassword,
DbName: impl.targetLoadConfig.TargetDs.DbName,
}
//DataType为map,解析数据列表中的key得到列名,且从数据库获取列类型信息
loadColumns, err = ParseDbColumn(ctx, impl.targetLoadConfig.TargetDs.DbType, dbConfig, impl.targetLoadConfig.TargetTable, columns, true)
if err != nil {
logrus.Errorf("saveOrUpdateLoad生成sql:解析map数据集中目标column的meta信息失败=>%s", err)
return nil, err
}
} else {
if transResult.DataType.Kind() != reflect.Struct {
logrus.Warnf("saveOrUpdateLoad生成sql:解析trd中的目标column失败,当前trd的数据类型[%v]不为struct", transResult.DataType.Kind())
return nil, errors.New("当前trd的数据类型只支持struct")
}
//DataType为结构体类型,解析load标签和属性得到列信息
trdType := transResult.DataType
fieldName := strings.TrimSpace(impl.targetLoadConfig.SourceField)
if fieldName != "" {
trdType = tools.FindFieldType(trdType, fieldName)
if trdType == nil {
logrus.Warnf("saveOrUpdateLoad生成sql:解析trd[%+v]中的SourceField[%s]失败", transResult.DataType, fieldName)
return nil, errors.New("无法从trd中找到配置的属性")
}
}
loadColumns = ParseLoadColumn(ctx, trdType, fieldName, impl.loadColumnConfigMap)
}
if len(loadColumns) == 0 {
logrus.Warnf("saveOrUpdateLoad生成sql:当前trd的数据类型[%v]解析目标column的meta信息为空", transResult.DataType)
return nil, errors.New("目标column的meta信息为空")
}
//设置字段跳过更新
for _, lc := range loadColumns {
cfg := impl.loadColumnConfigMap[lc.ColumnName]
if cfg != nil {
if cfg.SkipUpdate {
lc.SkipUpdate = true
}
}
}
dataSize := len(transResult.DataList)
sr := &SqlResult{
sqlList: make([]string, 0, dataSize),
paramList: make([][]any, 0, dataSize),
}
//解析配置中联合唯一的列
ukNames := parseUkNames(impl.targetLoadConfig.UkColumn)
/*
* 拼装insert信息:insert into table(xxxx) value(?,?) on duplicate key update a=?,b=?
*/
genCtx := &gen.GeneratorContext{
Ctx: ctx,
FromCache: impl.FromCache,
}
dmlDefine := &DmlDefine{
Table: impl.targetLoadConfig.TargetTable,
ColumnDefList: loadColumns,
InsertNull: impl.targetLoadConfig.InsertNull,
UpdateNull: impl.targetLoadConfig.UpdateNull,
UkNameList: ukNames,
}
var maxIncrementValue reflect.Value //遍历数据的同时,得到数据中增量字段的最大值
for i := 0; i < dataSize; i++ {
data := transResult.DataList[i] //transform结果的单条数据
//生成insert语句信息
insertStmt, err := GenerateInsert(genCtx, dmlDefine, data)
if err != nil {
logrus.Errorf("saveOrUpdateLoad生成sql:生成insert字句出错, 错误信息=>%s; 列定义信息=>%+v; 当前数据行=>%v;", err, dmlDefine, data)
return nil, err
}
rowCache := insertStmt.Cache
//生成update语句信息
updateStmt, err := GenerateOnDuplicateUpdate(genCtx, dmlDefine, data, rowCache)
if err != nil {
logrus.Errorf("saveOrUpdateLoad生成sql:生成OnDuplicateUpdate字句出错, 错误信息=>%s; 列定义信息=>%+v; 当前数据行=>%v;", err, dmlDefine, data)
return nil, err
}
//计算增量字段最大的数据
if incrConfig != nil {
var incrColumn *LoadColumn
for _, col := range loadColumns {
if col.FieldName == incrConfig.IncrementTransformField {
incrColumn = col
break
}
}
if incrColumn != nil {
ifValue := rowCache[incrColumn.ColumnName]
pfv := reflect.ValueOf(ifValue)
if !maxIncrementValue.IsValid() {
maxIncrementValue = pfv
} else {
cv := tools.CompareAndGetMaxValue(maxIncrementValue, pfv)
if cv.IsValid() {
maxIncrementValue = cv
}
}
}
}
//添加sql和参数返回结果
if updateStmt != nil {
sql := fmt.Sprintf("%s%s", insertStmt.Sql, updateStmt.Sql)
sr.sqlList = append(sr.sqlList, sql)
size := len(insertStmt.ParamList) + len(updateStmt.ParamList)
params := make([]any, 0, size)
params = append(params, insertStmt.ParamList...)
params = append(params, updateStmt.ParamList...)
sr.paramList = append(sr.paramList, params)
} else {
sr.sqlList = append(sr.sqlList, insertStmt.Sql)
sr.paramList = append(sr.paramList, insertStmt.ParamList)
}
}
if incrConfig != nil && maxIncrementValue.IsValid() {
v, _ := tools.BasicTypeToString(maxIncrementValue)
sr.endPosition = &vo.Position{
Config: incrConfig,
Value: v,
}
}
return sr, nil
}
这个逻辑生成的SQL语句是什么样子的