Nessuna descrizione
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

query_csv.go 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. package functions
  2. import (
  3. "database/sql"
  4. "encoding/csv"
  5. "fmt"
  6. "strings"
  7. "github.com/jmoiron/sqlx"
  8. )
  9. // QueryToCSV 无参数查询并返回 CSV 字节数据
  10. func QueryToCSV(db *sqlx.DB, sql string) ([]byte, error) {
  11. if sql == "" {
  12. return nil, fmt.Errorf("SQL query cannot be empty")
  13. }
  14. rows, err := db.Query(sql)
  15. if err != nil {
  16. return nil, fmt.Errorf("query execution failed: %v", err)
  17. }
  18. return rowsToCSV(rows)
  19. }
  20. // QueryParamsToCSV 位置参数查询并返回 CSV 字节数据
  21. func QueryPositionalToCSV(db *sqlx.DB, sql string, positionalParams ...interface{}) ([]byte, error) {
  22. if sql == "" {
  23. return nil, fmt.Errorf("SQL query cannot be empty")
  24. }
  25. rows, err := db.Query(sql, positionalParams)
  26. if err != nil {
  27. return nil, fmt.Errorf("query execution failed: %v", err)
  28. }
  29. return rowsToCSV(rows)
  30. }
  31. // QueryParamsNameToCSV 命名参数查询并返回 CSV 字节数据
  32. // params 可以是 map[string]interface{} 或结构体
  33. func QueryParamsNameToCSV(db *sqlx.DB, sql string, params map[string]interface{}) ([]byte, error) {
  34. if sql == "" {
  35. return nil, fmt.Errorf("SQL query cannot be empty")
  36. }
  37. query, args, err := sqlx.Named(sql, params)
  38. if err != nil {
  39. return nil, fmt.Errorf("failed to bind named parameters: %v", err)
  40. }
  41. query = db.Rebind(query)
  42. rows, err := db.Query(query, args...)
  43. if err != nil {
  44. return nil, fmt.Errorf("query execution failed: %v", err)
  45. }
  46. return rowsToCSV(rows)
  47. }
  48. // / rowsToCSV 公共方法:将查询结果转换为 CSV 字节数据
  49. func rowsToCSV(rows *sql.Rows) ([]byte, error) {
  50. defer rows.Close()
  51. columns, err := rows.Columns()
  52. if err != nil {
  53. return nil, fmt.Errorf("failed to get columns: %v", err)
  54. }
  55. var builder strings.Builder
  56. writer := csv.NewWriter(&builder)
  57. // 写入表头
  58. if err := writer.Write(columns); err != nil {
  59. return nil, fmt.Errorf("failed to write CSV header: %v", err)
  60. }
  61. for rows.Next() {
  62. values := make([]interface{}, len(columns))
  63. valuePtrs := make([]any, len(columns))
  64. for i := range columns {
  65. valuePtrs[i] = &values[i]
  66. }
  67. if err := rows.Scan(valuePtrs...); err != nil {
  68. return nil, fmt.Errorf("failed to scan row: %v", err)
  69. }
  70. // 所有值转为字符串
  71. row := make([]string, len(columns))
  72. for i, val := range values {
  73. if val == nil {
  74. row[i] = ""
  75. } else {
  76. row[i] = fmt.Sprintf("%v", val)
  77. }
  78. }
  79. if err := writer.Write(row); err != nil {
  80. return nil, fmt.Errorf("failed to write CSV row: %v", err)
  81. }
  82. }
  83. writer.Flush()
  84. if err := writer.Error(); err != nil {
  85. return nil, fmt.Errorf("failed to flush CSV: %v", err)
  86. }
  87. if err := rows.Err(); err != nil {
  88. return nil, fmt.Errorf("row iteration error: %v", err)
  89. }
  90. return []byte(builder.String()), nil
  91. }