120 lines
2.7 KiB
Go
120 lines
2.7 KiB
Go
package db
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"excel_export/biz/export"
|
|
"fmt"
|
|
"gorm.io/driver/mysql"
|
|
"gorm.io/gorm"
|
|
"runtime/trace"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
var _ export.DataFetcher = new(Db)
|
|
|
|
type Db struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
func NewDb(str string) (*Db, error) {
|
|
db, err := gorm.Open(
|
|
mysql.Open(str+""),
|
|
&gorm.Config{
|
|
//Logger: logger.Discard,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
db = db.Debug()
|
|
return &Db{
|
|
db: db,
|
|
}, nil
|
|
}
|
|
|
|
func (d *Db) Fetch(s string) (*export.Data, error) {
|
|
fetchRegion := trace.StartRegion(context.Background(), "db.fetch")
|
|
defer func() {
|
|
fetchRegion.End()
|
|
}()
|
|
rows, err := d.db.Raw(s).Rows()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
//titles := make([]string, 0, 10)
|
|
titles, err := rows.Columns()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
data := getData(rows, d.db, titles)
|
|
|
|
//vv := transform(titles, dd)
|
|
//fmt.Println(vv)
|
|
//f, err := os.Create("./ff.csv")
|
|
//
|
|
//w := csv.NewWriter(f)
|
|
//w.Write(titles)
|
|
//w.WriteAll(vv)
|
|
////w.Flush()
|
|
//f.Close()
|
|
|
|
return &export.Data{
|
|
Title: titles,
|
|
Data: data,
|
|
}, nil
|
|
}
|
|
|
|
func getData(rows *sql.Rows, db *gorm.DB, titles []string) [][]string {
|
|
result := make([][]string, 0, 10)
|
|
for rows.Next() {
|
|
var row map[string]interface{}
|
|
db.ScanRows(rows, &row)
|
|
result = append(result, transformRow(titles, row))
|
|
}
|
|
return result
|
|
}
|
|
|
|
func transform(titles []string, data []map[string]interface{}) [][]string {
|
|
result := make([][]string, len(data))
|
|
for i, m := range data {
|
|
result[i] = transformRow(titles, m)
|
|
}
|
|
return result
|
|
}
|
|
|
|
func transformRow(titles []string, data map[string]interface{}) []string {
|
|
row := make([]string, 0, len(data))
|
|
for _, title := range titles {
|
|
col := data[title]
|
|
switch v := col.(type) {
|
|
case string:
|
|
row = append(row, v)
|
|
case time.Time:
|
|
row = append(row, v.Format("2006-01-02 15:04:05"))
|
|
case int, int8, int16, int32, int64:
|
|
row = append(row, fmt.Sprintf("%d", v))
|
|
case float64:
|
|
// When formatting floats, do not use fmt.Sprintf("%v", n), this will cause numbers below 1e-4 to be printed in
|
|
// scientific notation. Scientific notation is not a valid way to store numbers in XML.
|
|
// Also not not use fmt.Sprintf("%f", n), this will cause numbers to be stored as X.XXXXXX. Which means that
|
|
// numbers will lose precision and numbers with fewer significant digits such as 0 will be stored as 0.000000
|
|
// which causes tests to fail.
|
|
row = append(row, strconv.FormatFloat(v, 'f', -1, 64))
|
|
case float32:
|
|
row = append(row, strconv.FormatFloat(float64(v), 'f', -1, 32))
|
|
case []byte:
|
|
row = append(row, string(v))
|
|
case nil:
|
|
row = append(row, "")
|
|
default:
|
|
row = append(row, fmt.Sprintf("%v", v))
|
|
}
|
|
}
|
|
return row
|
|
|
|
}
|