説明なし
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

query_csv.go 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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.NamedQuery(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 := sqlx.NamedQuery(db, sql, params)
  43. if err != nil {
  44. return nil, fmt.Errorf("query execution failed: %v", err)
  45. }
  46. defer rows.Close()
  47. return rowsToCSV(rows.Rows)
  48. }
  49. // / rowsToCSV 公共方法:将查询结果转换为 CSV 字节数据
  50. func rowsToCSV(rows *sql.Rows) ([]byte, error) {
  51. defer rows.Close()
  52. columns, err := rows.Columns()
  53. if err != nil {
  54. return nil, fmt.Errorf("failed to get columns: %v", err)
  55. }
  56. var builder strings.Builder
  57. writer := csv.NewWriter(&builder)
  58. // 写入表头
  59. if err := writer.Write(columns); err != nil {
  60. return nil, fmt.Errorf("failed to write CSV header: %v", err)
  61. }
  62. for rows.Next() {
  63. values := make([]interface{}, len(columns))
  64. valuePtrs := make([]any, len(columns))
  65. for i := range columns {
  66. valuePtrs[i] = &values[i]
  67. }
  68. if err := rows.Scan(valuePtrs...); err != nil {
  69. return nil, fmt.Errorf("failed to scan row: %v", err)
  70. }
  71. // 所有值转为字符串
  72. row := make([]string, len(columns))
  73. for i, val := range values {
  74. if val == nil {
  75. row[i] = ""
  76. } else {
  77. row[i] = fmt.Sprintf("%v", val)
  78. }
  79. }
  80. if err := writer.Write(row); err != nil {
  81. return nil, fmt.Errorf("failed to write CSV row: %v", err)
  82. }
  83. }
  84. writer.Flush()
  85. if err := writer.Error(); err != nil {
  86. return nil, fmt.Errorf("failed to flush CSV: %v", err)
  87. }
  88. if err := rows.Err(); err != nil {
  89. return nil, fmt.Errorf("row iteration error: %v", err)
  90. }
  91. return []byte(builder.String()), nil
  92. }