Нет описания
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

query_csv.go 2.8KB

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