github.com/team-ide/go-dialect@v1.9.20/worker/task_import.go (about) 1 package worker 2 3 import ( 4 "database/sql" 5 "errors" 6 "fmt" 7 "github.com/team-ide/go-dialect/dialect" 8 "path/filepath" 9 "strings" 10 ) 11 12 func NewTaskImport(db *sql.DB, dia dialect.Dialect, newDb func(owner *TaskImportOwner) (db *sql.DB, err error), taskImportParam *TaskImportParam) (res *taskImport) { 13 if taskImportParam.DataSourceType == nil { 14 taskImportParam.DataSourceType = DataSourceTypeSql 15 } 16 task := &Task{ 17 dia: dia, 18 db: db, 19 onProgress: taskImportParam.OnProgress, 20 } 21 res = &taskImport{ 22 Task: task, 23 TaskImportParam: taskImportParam, 24 newDb: newDb, 25 } 26 task.do = res.do 27 return 28 } 29 30 type TaskImportParam struct { 31 Owners []*TaskImportOwner `json:"owners"` 32 33 DataSourceType *DataSourceType `json:"dataSourceType"` 34 BatchNumber int `json:"batchNumber"` 35 OwnerCreateIfNotExist bool `json:"ownerCreateIfNotExist"` 36 ErrorContinue bool `json:"errorContinue"` 37 38 FormatIndexName func(ownerName string, tableName string, index *dialect.IndexModel) string `json:"-"` 39 OnProgress func(progress *TaskProgress) 40 } 41 42 type TaskImportOwner struct { 43 Name string `json:"name"` 44 Path string `json:"path"` 45 SkipTableNames []string `json:"skipTableNames"` 46 Tables []*TaskImportTable `json:"tables"` 47 Username string `json:"username"` 48 Password string `json:"password"` 49 } 50 51 type TaskImportTable struct { 52 Name string `json:"name"` 53 Path string `json:"path"` 54 Columns []*TaskImportColumn `json:"columns"` 55 } 56 57 type TaskImportColumn struct { 58 Name string `json:"name"` 59 Value string `json:"value"` 60 } 61 62 type taskImport struct { 63 *Task 64 *TaskImportParam `json:"-"` 65 newDb func(owner *TaskImportOwner) (db *sql.DB, err error) 66 } 67 68 func (this_ *taskImport) do() (err error) { 69 70 defer func() { 71 if e := recover(); e != nil { 72 err = errors.New(fmt.Sprint(e)) 73 } 74 }() 75 owners := this_.Owners 76 if len(owners) == 0 { 77 return 78 } 79 this_.countIncr(&this_.OwnerCount, len(owners)) 80 for _, owner := range owners { 81 var success bool 82 success, err = this_.importOwner(owner) 83 if success { 84 this_.countIncr(&this_.OwnerSuccessCount, 1) 85 } else { 86 this_.countIncr(&this_.OwnerErrorCount, 1) 87 } 88 if err != nil { 89 return 90 } 91 } 92 93 return 94 } 95 96 func (this_ *taskImport) importOwner(owner *TaskImportOwner) (success bool, err error) { 97 progress := &TaskProgress{ 98 Title: "导入[" + owner.Name + "]", 99 } 100 defer func() { 101 if e := recover(); e != nil { 102 err = errors.New(fmt.Sprint(e)) 103 } 104 if err != nil { 105 progress.Error = err.Error() 106 if progress.OnError != nil { 107 progress.OnError(err) 108 } 109 } 110 111 if this_.ErrorContinue { 112 err = nil 113 } 114 }() 115 116 this_.addProgress(progress) 117 118 if this_.IsStop { 119 return 120 } 121 122 ownerName := owner.Name 123 124 // 125 if this_.OwnerCreateIfNotExist { 126 var ownerOne *dialect.OwnerModel 127 ownerOne, err = OwnerSelect(this_.db, this_.dia, this_.Param, ownerName) 128 if err != nil { 129 return 130 } 131 if ownerOne == nil { 132 this_.addProgress(&TaskProgress{ 133 Title: "导入[" + owner.Name + "] 不存在,创建", 134 }) 135 _, err = OwnerCreate(this_.db, this_.dia, this_.Param, &dialect.OwnerModel{ 136 OwnerName: ownerName, 137 OwnerPassword: owner.Password, 138 OwnerCharacterSetName: "utf8mb4", 139 }) 140 if err != nil { 141 return 142 } 143 } else { 144 this_.addProgress(&TaskProgress{ 145 Title: "导入[" + owner.Name + "] 存在", 146 }) 147 } 148 } 149 150 workDb, err := this_.newDb(owner) 151 if err != nil { 152 return 153 } 154 155 if owner.Path != "" { 156 var exists bool 157 exists, err = PathExists(owner.Path) 158 if err != nil { 159 return 160 } 161 if !exists { 162 err = errors.New("import [" + ownerName + "] path [" + owner.Path + "] not exists.") 163 return 164 } 165 } 166 167 if this_.DataSourceType == DataSourceTypeSql { 168 if owner.Path != "" { 169 var isDir bool 170 isDir, err = PathIsDir(owner.Path) 171 if err != nil { 172 return 173 } 174 if !isDir { 175 _, err = this_.importSql(workDb, ownerName, owner.Path) 176 if err != nil { 177 return 178 } 179 } 180 } 181 182 } 183 tables := owner.Tables 184 this_.countIncr(&this_.TableCount, len(tables)) 185 186 for _, table := range tables { 187 tableName := table.Name 188 if len(owner.SkipTableNames) > 0 { 189 var skip bool 190 for _, skipTableName := range owner.SkipTableNames { 191 if strings.EqualFold(tableName, skipTableName) { 192 skip = true 193 } 194 } 195 if skip { 196 this_.countIncr(&this_.TableSuccessCount, 1) 197 continue 198 } 199 } 200 var success_ bool 201 success_, err = this_.importTable(workDb, owner.Name, tableName, owner.Path, table.Path, table.Columns) 202 if success_ { 203 this_.countIncr(&this_.TableSuccessCount, 1) 204 } else { 205 this_.countIncr(&this_.TableErrorCount, 1) 206 } 207 if err != nil { 208 return 209 } 210 } 211 212 success = true 213 return 214 } 215 216 func (this_ *taskImport) importSql(workDb *sql.DB, ownerName string, path string) (success bool, err error) { 217 progress := &TaskProgress{ 218 Title: "导入[" + ownerName + "]", 219 } 220 defer func() { 221 if e := recover(); e != nil { 222 err = errors.New(fmt.Sprint(e)) 223 } 224 if err != nil { 225 progress.Error = err.Error() 226 if progress.OnError != nil { 227 progress.OnError(err) 228 } 229 } 230 231 if this_.ErrorContinue { 232 err = nil 233 } 234 }() 235 236 this_.addProgress(progress) 237 238 if this_.IsStop { 239 return 240 } 241 242 param := &DataSourceParam{ 243 Path: path, 244 SheetName: ownerName, 245 Dia: this_.dia, 246 } 247 ownerDataSource := this_.DataSourceType.New(param) 248 err = ownerDataSource.ReadStart() 249 if err != nil { 250 return 251 } 252 defer func() { 253 _ = ownerDataSource.ReadEnd() 254 }() 255 err = ownerDataSource.Read(nil, func(data *DataSourceData) (err error) { 256 257 if this_.IsStop { 258 return 259 } 260 261 if data.HasSql { 262 this_.countIncr(&this_.DataCount, 1) 263 264 var result sql.Result 265 result, err = DoExec(workDb, data.Sql, nil) 266 if err != nil { 267 this_.countIncr(&this_.DataErrorCount, 1) 268 if !this_.ErrorContinue { 269 err = errors.New("sql:" + data.Sql + " exec error," + err.Error()) 270 return 271 } 272 err = nil 273 } 274 rowsAffected, _ := result.RowsAffected() 275 this_.countIncr(&this_.DataSuccessCount, int(rowsAffected)) 276 } 277 return 278 }) 279 if err != nil { 280 return 281 } 282 success = true 283 return 284 } 285 286 func (this_ *taskImport) importTable(workDb *sql.DB, ownerName string, tableName string, ownerPath string, tablePath string, columns []*TaskImportColumn) (success bool, err error) { 287 288 progress := &TaskProgress{ 289 Title: "导入[" + ownerName + "." + tableName + "]", 290 } 291 defer func() { 292 if e := recover(); e != nil { 293 err = errors.New(fmt.Sprint(e)) 294 } 295 if err != nil { 296 progress.Error = err.Error() 297 if progress.OnError != nil { 298 progress.OnError(err) 299 } 300 } 301 302 if this_.ErrorContinue { 303 err = nil 304 } 305 }() 306 307 this_.addProgress(progress) 308 309 if this_.IsStop { 310 return 311 } 312 313 if tablePath == "" { 314 if ownerPath == "" { 315 err = errors.New("import [" + ownerName + "." + tableName + "] table path is empty.") 316 return 317 } 318 tablePath = ownerPath + string(filepath.Separator) + tableName + "." + this_.DataSourceType.FileSuffix 319 320 var exists bool 321 exists, err = PathExists(tablePath) 322 if err != nil { 323 return 324 } 325 if !exists { 326 err = errors.New("import [" + ownerName + "." + tableName + "] path [" + tablePath + "] not exists.") 327 return 328 } 329 var isDir bool 330 isDir, err = PathIsDir(tablePath) 331 if err != nil { 332 return 333 } 334 if isDir { 335 err = errors.New("import [" + ownerName + "." + tableName + "] path [" + tablePath + "] is dir.") 336 return 337 } 338 } 339 340 if this_.DataSourceType == DataSourceTypeSql { 341 _, err = this_.importSql(workDb, ownerName, tablePath) 342 if err != nil { 343 return 344 } 345 } else { 346 var tableDetail *dialect.TableModel 347 tableDetail, err = TableDetail(workDb, this_.dia, this_.Param, ownerName, tableName, false) 348 if err != nil { 349 return 350 } 351 if tableDetail == nil { 352 err = errors.New("source db table [" + ownerName + "." + tableName + "] is not exist") 353 return 354 } 355 356 var tableDataSource DataSource 357 param := &DataSourceParam{ 358 Path: tablePath, 359 SheetName: tableName, 360 Dia: this_.dia, 361 } 362 tableDataSource = this_.DataSourceType.New(param) 363 err = tableDataSource.ReadStart() 364 if err != nil { 365 return 366 } 367 defer func() { 368 _ = tableDataSource.ReadEnd() 369 }() 370 371 //if this_.ImportStructure { 372 // err = this_.exportTableStructure(ownerDataSource, tableDataSource, tableDetail, targetOwnerName, targetTableName) 373 // if err != nil { 374 // return 375 // } 376 //} 377 err = this_.importTableData(workDb, tableDataSource, tableDetail, ownerName, tableName, columns) 378 if err != nil { 379 return 380 } 381 } 382 383 success = true 384 return 385 } 386 func (this_ *taskImport) importTableData(workDb *sql.DB, tableDataSource DataSource, tableDetail *dialect.TableModel, targetOwnerName string, targetTableName string, columns []*TaskImportColumn) (err error) { 387 388 progress := &TaskProgress{ 389 Title: "导入表数据[" + tableDetail.OwnerName + "." + tableDetail.TableName + "] 到 [" + targetOwnerName + "." + targetTableName + "]", 390 } 391 defer func() { 392 if e := recover(); e != nil { 393 err = errors.New(fmt.Sprint(e)) 394 } 395 if err != nil { 396 progress.Error = err.Error() 397 if progress.OnError != nil { 398 progress.OnError(err) 399 } 400 } 401 402 if this_.ErrorContinue { 403 err = nil 404 } 405 }() 406 407 this_.addProgress(progress) 408 409 if this_.IsStop { 410 return 411 } 412 413 batchNumber := this_.BatchNumber 414 if batchNumber <= 0 { 415 batchNumber = 100 416 } 417 var columnCache = make(map[string]*dialect.ColumnModel) 418 for _, one := range tableDetail.ColumnList { 419 columnCache[one.ColumnName] = one 420 } 421 var newColumnList = tableDetail.ColumnList 422 if len(columns) > 0 { 423 newColumnList = []*dialect.ColumnModel{} 424 for _, one := range columns { 425 column := columnCache[one.Name] 426 newColumn := &dialect.ColumnModel{} 427 newColumn.ColumnName = one.Name 428 if column != nil { 429 newColumn.ColumnDataType = column.ColumnDataType 430 newColumn.ColumnDefault = column.ColumnDefault 431 newColumn.ColumnLength = column.ColumnLength 432 newColumn.ColumnPrecision = column.ColumnPrecision 433 newColumn.ColumnScale = column.ColumnScale 434 } 435 newColumnList = append(newColumnList, newColumn) 436 } 437 } 438 439 var dataList []map[string]interface{} 440 441 err = tableDataSource.Read(newColumnList, func(data *DataSourceData) (err error) { 442 443 if this_.IsStop { 444 return 445 } 446 if data.HasData && data.Data != nil { 447 dataList = append(dataList, data.Data) 448 this_.countIncr(&this_.DataCount, 1) 449 if len(dataList) >= batchNumber { 450 err = this_.importDataList(workDb, dataList, targetOwnerName, targetTableName, newColumnList) 451 dataList = make([]map[string]interface{}, 0) 452 if err != nil { 453 return 454 } 455 } 456 457 } 458 return 459 }) 460 if err != nil { 461 return 462 } 463 if len(dataList) >= 0 { 464 465 if this_.IsStop { 466 return 467 } 468 469 err = this_.importDataList(workDb, dataList, targetOwnerName, targetTableName, newColumnList) 470 dataList = make([]map[string]interface{}, 0) 471 if err != nil { 472 return 473 } 474 } 475 return 476 } 477 478 func (this_ *taskImport) importDataList(workDb *sql.DB, dataList []map[string]interface{}, ownerName string, tableName string, columnList []*dialect.ColumnModel) (err error) { 479 480 dataListCount := len(dataList) 481 progress := &TaskProgress{ 482 Title: "插入数据[" + ownerName + "." + tableName + "]", 483 } 484 defer func() { 485 if e := recover(); e != nil { 486 err = errors.New(fmt.Sprint(e)) 487 } 488 if err != nil { 489 progress.Error = err.Error() 490 if progress.OnError != nil { 491 progress.OnError(err) 492 } 493 this_.countIncr(&this_.DataErrorCount, dataListCount) 494 } else { 495 this_.countIncr(&this_.DataSuccessCount, dataListCount) 496 } 497 498 if this_.ErrorContinue { 499 err = nil 500 } 501 }() 502 503 this_.addProgress(progress) 504 505 if this_.IsStop { 506 return 507 } 508 509 this_.countIncr(&this_.DataReadyCount, dataListCount) 510 511 var newColumnList []*dialect.ColumnModel 512 for _, one := range columnList { 513 if one.ColumnName != "" { 514 newColumnList = append(newColumnList, one) 515 } 516 } 517 518 _, _, batchSqlList, batchValuesList, err := this_.dia.DataListInsertSql(this_.Param, ownerName, tableName, newColumnList, dataList) 519 if err != nil { 520 return 521 } 522 var errSql string 523 _, errSql, _, err = DoExecs(workDb, batchSqlList, batchValuesList) 524 if err != nil { 525 if errSql != "" { 526 err = errors.New("sql:" + errSql + " exec error," + err.Error()) 527 } 528 return 529 } 530 return 531 }