Просмотр исходного кода

增加sql带参数的查询方法

qdy 3 месяцев назад
Родитель
Сommit
1c491b2b42
4 измененных файлов: 286 добавлений и 522 удалений
  1. 20
    15
      factory/db_factory.go
  2. 0
    507
      functions/query.go
  3. 114
    0
      functions/query_csv.go
  4. 152
    0
      functions/query_json.go

+ 20
- 15
factory/db_factory.go Просмотреть файл

@@ -2,7 +2,6 @@ package factory
2 2
 
3 3
 import (
4 4
 	"fmt"
5
-	"io"
6 5
 	"sync"
7 6
 
8 7
 	"git.x2erp.com/qdy/go-base/config"
@@ -118,29 +117,35 @@ func (f *DBFactory) QueryToJSON(sql string) *types.QueryResult {
118 117
 	return functions.QueryToJSON(f.db, sql)
119 118
 }
120 119
 
120
+// QueryParamsToJSON 位置参数查询并返回 JSON 字节数据
121
+func (f *DBFactory) QueryPositionalToJSON(db *sqlx.DB, sql string, params ...interface{}) *types.QueryResult {
122
+
123
+	return functions.QueryPositionalToJSON(f.db, sql, params)
124
+}
125
+
126
+// QueryParamsNameToJSON 命名参数查询并返回 JSON 字节数据
127
+// params 可以是 map[string]interface{} 或结构体
128
+func (f *DBFactory) QueryParamsNameToJSON(db *sqlx.DB, sql string, params map[string]interface{}) *types.QueryResult {
129
+
130
+	return functions.QueryParamsNameToJSON(f.db, sql, params)
131
+}
132
+
121 133
 // QueryToCSV 快捷查询,直接返回 CSV 字符串(包含表头)
122 134
 func (f *DBFactory) QueryToCSV(sql string) ([]byte, error) {
123 135
 	return functions.QueryToCSV(f.db, sql)
124 136
 }
125 137
 
126
-// QueryWithColumns 快捷查询,返回完整结果(含列信息)
127
-func (f *DBFactory) QueryWithColumns(sql string) *types.QueryResult {
128
-	return functions.QueryWithColumns(f.db, sql)
129
-}
138
+// QueryParamsToCSV 位置参数查询并返回 CSV 字节数据
139
+func (f *DBFactory) QueryPositionalToCSV(db *sqlx.DB, sql string, params ...interface{}) ([]byte, error) {
130 140
 
131
-// QueryDataOnly 快捷查询,返回纯数据(性能优先)
132
-func (f *DBFactory) QueryDataOnly(sql string) *types.QueryResult {
133
-	return functions.QueryDataOnly(f.db, sql)
141
+	return functions.QueryPositionalToCSV(f.db, sql, params)
134 142
 }
135 143
 
136
-// QueryCSV 快捷查询,返回 CSV 格式结果(支持自定义是否包含表头)
137
-func (f *DBFactory) QueryCSV(sql string, includeHeader bool) *types.QueryResult {
138
-	return functions.QueryCSV(f.db, sql, includeHeader)
139
-}
144
+// QueryParamsNameToCSV 命名参数查询并返回 CSV 字节数据
145
+// params 可以是 map[string]interface{} 或结构体
146
+func (f *DBFactory) QueryParamsNameToCSV(db *sqlx.DB, sql string, params ...interface{}) ([]byte, error) {
140 147
 
141
-// QueryCSVStream 快捷流式输出 CSV(直接写入 io.Writer,适合大文件)
142
-func (f *DBFactory) QueryCSVStream(sql string, w io.Writer, includeHeader bool) (int, error) {
143
-	return functions.QueryCSVStream(f.db, sql, w, includeHeader)
148
+	return functions.QueryParamsNameToCSV(f.db, sql, params)
144 149
 }
145 150
 
146 151
 // ExecuteDDL 快捷执行DDL语句

+ 0
- 507
functions/query.go Просмотреть файл

@@ -1,507 +0,0 @@
1
-package functions
2
-
3
-import (
4
-	"encoding/csv"
5
-	"encoding/json"
6
-	"fmt"
7
-	"io"
8
-	"strings"
9
-	"time"
10
-
11
-	"git.x2erp.com/qdy/go-base/types"
12
-	"github.com/jmoiron/sqlx"
13
-)
14
-
15
-// QueryToJSON 执行查询并返回JSON格式数据(统一返回QueryResult)
16
-func QueryToJSON(db *sqlx.DB, sql string) *types.QueryResult {
17
-	startTime := time.Now()
18
-	result := &types.QueryResult{}
19
-
20
-	if sql == "" {
21
-		result.Success = false
22
-		result.Error = "SQL query cannot be empty"
23
-		result.Time = time.Since(startTime).String()
24
-		return result
25
-	}
26
-
27
-	rows, err := db.Query(sql)
28
-	if err != nil {
29
-		result.Success = false
30
-		result.Error = fmt.Sprintf("Query execution failed: %v", err)
31
-		result.Time = time.Since(startTime).String()
32
-		return result
33
-	}
34
-	defer rows.Close()
35
-
36
-	columns, err := rows.Columns()
37
-	if err != nil {
38
-		result.Success = false
39
-		result.Error = fmt.Sprintf("Failed to get columns: %v", err)
40
-		result.Time = time.Since(startTime).String()
41
-		return result
42
-	}
43
-
44
-	var results []map[string]interface{}
45
-	count := 0
46
-
47
-	for rows.Next() {
48
-		count++
49
-		values := make([]interface{}, len(columns))
50
-		valuePtrs := make([]interface{}, len(columns))
51
-		for i := range columns {
52
-			valuePtrs[i] = &values[i]
53
-		}
54
-
55
-		if err := rows.Scan(valuePtrs...); err != nil {
56
-			result.Success = false
57
-			result.Error = fmt.Sprintf("Failed to scan row: %v", err)
58
-			result.Time = time.Since(startTime).String()
59
-			return result
60
-		}
61
-
62
-		resultMap := make(map[string]interface{})
63
-		for i, col := range columns {
64
-			// 完全不处理类型,直接赋值,让 json.Marshal 自己处理
65
-			resultMap[col] = values[i]
66
-		}
67
-		results = append(results, resultMap)
68
-	}
69
-
70
-	if err := rows.Err(); err != nil {
71
-		result.Success = false
72
-		result.Error = fmt.Sprintf("Row iteration error: %v", err)
73
-		result.Time = time.Since(startTime).String()
74
-		return result
75
-	}
76
-
77
-	jsonData, err := json.Marshal(results)
78
-	if err != nil {
79
-		result.Success = false
80
-		result.Error = fmt.Sprintf("JSON marshal failed: %v", err)
81
-		result.Time = time.Since(startTime).String()
82
-		return result
83
-	}
84
-
85
-	result.Success = true
86
-	result.Data = map[string]interface{}{
87
-		"json":  string(jsonData),
88
-		"rows":  results,
89
-		"count": count,
90
-	}
91
-	result.Count = count
92
-	result.Time = time.Since(startTime).String()
93
-	return result
94
-}
95
-
96
-// QueryToCSV 查询并返回 CSV 字节数据(包含表头)
97
-func QueryToCSV(db *sqlx.DB, sql string) ([]byte, error) {
98
-
99
-	if sql == "" {
100
-		return nil, fmt.Errorf("SQL query cannot be empty")
101
-	}
102
-
103
-	rows, err := db.Query(sql)
104
-	if err != nil {
105
-		return nil, fmt.Errorf("query execution failed: %v", err)
106
-	}
107
-	defer rows.Close()
108
-
109
-	columns, err := rows.Columns()
110
-	if err != nil {
111
-		return nil, fmt.Errorf("failed to get columns: %v", err)
112
-	}
113
-
114
-	var builder strings.Builder
115
-	writer := csv.NewWriter(&builder)
116
-
117
-	// 写入表头
118
-	//if err := writer.Write(columns); err != nil {
119
-	//	return nil, fmt.Errorf("failed to write CSV header: %v", err)
120
-	//}
121
-
122
-	count := 0
123
-	for rows.Next() {
124
-		count++
125
-		values := make([]interface{}, len(columns))
126
-		valuePtrs := make([]any, len(columns))
127
-		for i := range columns {
128
-			valuePtrs[i] = &values[i]
129
-		}
130
-
131
-		if err := rows.Scan(valuePtrs...); err != nil {
132
-			return nil, fmt.Errorf("failed to scan row: %v", err)
133
-		}
134
-
135
-		// 所有值转为字符串
136
-		row := make([]string, len(columns))
137
-		for i, val := range values {
138
-			if val == nil {
139
-				row[i] = ""
140
-			} else {
141
-				row[i] = fmt.Sprintf("%v", val)
142
-			}
143
-		}
144
-
145
-		if err := writer.Write(row); err != nil {
146
-			return nil, fmt.Errorf("failed to write CSV row: %v", err)
147
-		}
148
-	}
149
-
150
-	writer.Flush()
151
-	if err := writer.Error(); err != nil {
152
-		return nil, fmt.Errorf("failed to flush CSV: %v", err)
153
-	}
154
-
155
-	if err := rows.Err(); err != nil {
156
-		return nil, fmt.Errorf("row iteration error: %v", err)
157
-	}
158
-
159
-	return []byte(builder.String()), nil
160
-}
161
-
162
-// ExecuteQueryWithColumns 执行查询并返回完整结果(包含列信息)
163
-func QueryWithColumns(db *sqlx.DB, sql string) *types.QueryResult {
164
-	startTime := time.Now()
165
-	result := &types.QueryResult{}
166
-
167
-	if sql == "" {
168
-		result.Success = false
169
-		result.Error = "SQL query cannot be empty"
170
-		result.Time = time.Since(startTime).String()
171
-		return result
172
-	}
173
-
174
-	rows, err := db.Query(sql)
175
-	if err != nil {
176
-		result.Success = false
177
-		result.Error = fmt.Sprintf("Query execution failed: %v", err)
178
-		result.Time = time.Since(startTime).String()
179
-		return result
180
-	}
181
-	defer rows.Close()
182
-
183
-	columns, err := rows.Columns()
184
-	if err != nil {
185
-		result.Success = false
186
-		result.Error = fmt.Sprintf("Failed to get columns: %v", err)
187
-		result.Time = time.Since(startTime).String()
188
-		return result
189
-	}
190
-
191
-	var results []map[string]interface{}
192
-	count := 0
193
-
194
-	for rows.Next() {
195
-		count++
196
-
197
-		values := make([]interface{}, len(columns))
198
-		valuePtrs := make([]interface{}, len(columns))
199
-		for i := range columns {
200
-			valuePtrs[i] = &values[i]
201
-		}
202
-
203
-		if err := rows.Scan(valuePtrs...); err != nil {
204
-			result.Success = false
205
-			result.Error = fmt.Sprintf("Failed to scan row: %v", err)
206
-			result.Time = time.Since(startTime).String()
207
-			return result
208
-		}
209
-
210
-		resultRow := make(map[string]interface{})
211
-		for i, col := range columns {
212
-			val := values[i]
213
-			switch v := val.(type) {
214
-			case []byte:
215
-				resultRow[col] = string(v)
216
-			case time.Time:
217
-				resultRow[col] = v.Format(time.RFC3339)
218
-			default:
219
-				resultRow[col] = v
220
-			}
221
-		}
222
-
223
-		results = append(results, resultRow)
224
-	}
225
-
226
-	if err := rows.Err(); err != nil {
227
-		result.Success = false
228
-		result.Error = fmt.Sprintf("Row iteration error: %v", err)
229
-		result.Time = time.Since(startTime).String()
230
-		return result
231
-	}
232
-
233
-	result.Success = true
234
-	result.Data = results
235
-	result.Count = count
236
-	result.Time = time.Since(startTime).String()
237
-
238
-	return result
239
-}
240
-
241
-// ExecuteQueryDataOnly 执行查询并返回纯数据(不包含列信息,性能更高)
242
-func QueryDataOnly(db *sqlx.DB, sql string) *types.QueryResult {
243
-	startTime := time.Now()
244
-	result := &types.QueryResult{}
245
-
246
-	if sql == "" {
247
-		result.Success = false
248
-		result.Error = "SQL query cannot be empty"
249
-		result.Time = time.Since(startTime).String()
250
-		return result
251
-	}
252
-
253
-	rows, err := db.Query(sql)
254
-	if err != nil {
255
-		result.Success = false
256
-		result.Error = fmt.Sprintf("Query execution failed: %v", err)
257
-		result.Time = time.Since(startTime).String()
258
-		return result
259
-	}
260
-	defer rows.Close()
261
-
262
-	columns, err := rows.Columns()
263
-	if err != nil {
264
-		result.Success = false
265
-		result.Error = fmt.Sprintf("Failed to get columns: %v", err)
266
-		result.Time = time.Since(startTime).String()
267
-		return result
268
-	}
269
-
270
-	var results []interface{}
271
-	count := 0
272
-
273
-	for rows.Next() {
274
-		count++
275
-
276
-		values := make([]interface{}, len(columns))
277
-		valuePtrs := make([]interface{}, len(columns))
278
-		for i := range columns {
279
-			valuePtrs[i] = &values[i]
280
-		}
281
-
282
-		if err := rows.Scan(valuePtrs...); err != nil {
283
-			result.Success = false
284
-			result.Error = fmt.Sprintf("Failed to scan row: %v", err)
285
-			result.Time = time.Since(startTime).String()
286
-			return result
287
-		}
288
-
289
-		resultRow := make([]interface{}, len(columns))
290
-		for i, val := range values {
291
-			switch v := val.(type) {
292
-			case []byte:
293
-				resultRow[i] = string(v)
294
-			case time.Time:
295
-				resultRow[i] = v.Format(time.RFC3339)
296
-			default:
297
-				resultRow[i] = v
298
-			}
299
-		}
300
-
301
-		results = append(results, resultRow)
302
-	}
303
-
304
-	if err := rows.Err(); err != nil {
305
-		result.Success = false
306
-		result.Error = fmt.Sprintf("Row iteration error: %v", err)
307
-		result.Time = time.Since(startTime).String()
308
-		return result
309
-	}
310
-
311
-	result.Success = true
312
-	result.Data = map[string]interface{}{
313
-		"rows":  results,
314
-		"count": count,
315
-	}
316
-	result.Count = count
317
-	result.Time = time.Since(startTime).String()
318
-
319
-	return result
320
-}
321
-
322
-// ExecuteQueryCSV 执行查询并返回CSV格式数据
323
-func QueryCSV(db *sqlx.DB, sql string, includeHeader bool) *types.QueryResult {
324
-	startTime := time.Now()
325
-	result := &types.QueryResult{}
326
-
327
-	if sql == "" {
328
-		result.Success = false
329
-		result.Error = "SQL query cannot be empty"
330
-		result.Time = time.Since(startTime).String()
331
-		return result
332
-	}
333
-
334
-	rows, err := db.Query(sql)
335
-	if err != nil {
336
-		result.Success = false
337
-		result.Error = fmt.Sprintf("Query execution failed: %v", err)
338
-		result.Time = time.Since(startTime).String()
339
-		return result
340
-	}
341
-	defer rows.Close()
342
-
343
-	columns, err := rows.Columns()
344
-	if err != nil {
345
-		result.Success = false
346
-		result.Error = fmt.Sprintf("Failed to get columns: %v", err)
347
-		result.Time = time.Since(startTime).String()
348
-		return result
349
-	}
350
-
351
-	var csvBuilder strings.Builder
352
-	writer := csv.NewWriter(&csvBuilder)
353
-
354
-	if includeHeader {
355
-		if err := writer.Write(columns); err != nil {
356
-			result.Success = false
357
-			result.Error = fmt.Sprintf("Failed to write CSV header: %v", err)
358
-			result.Time = time.Since(startTime).String()
359
-			return result
360
-		}
361
-	}
362
-
363
-	count := 0
364
-
365
-	for rows.Next() {
366
-		count++
367
-
368
-		values := make([]interface{}, len(columns))
369
-		valuePtrs := make([]interface{}, len(columns))
370
-		for i := range columns {
371
-			valuePtrs[i] = &values[i]
372
-		}
373
-
374
-		if err := rows.Scan(valuePtrs...); err != nil {
375
-			result.Success = false
376
-			result.Error = fmt.Sprintf("Failed to scan row: %v", err)
377
-			result.Time = time.Since(startTime).String()
378
-			return result
379
-		}
380
-
381
-		rowData := make([]string, len(columns))
382
-		for i, val := range values {
383
-			if val == nil {
384
-				rowData[i] = ""
385
-				continue
386
-			}
387
-
388
-			switch v := val.(type) {
389
-			case []byte:
390
-				rowData[i] = string(v)
391
-			case string:
392
-				rowData[i] = v
393
-			case int, int8, int16, int32, int64:
394
-				rowData[i] = fmt.Sprintf("%d", v)
395
-			case uint, uint8, uint16, uint32, uint64:
396
-				rowData[i] = fmt.Sprintf("%d", v)
397
-			case float32, float64:
398
-				rowData[i] = fmt.Sprintf("%f", v)
399
-			case bool:
400
-				if v {
401
-					rowData[i] = "true"
402
-				} else {
403
-					rowData[i] = "false"
404
-				}
405
-			case time.Time:
406
-				rowData[i] = v.Format(time.RFC3339)
407
-			default:
408
-				rowData[i] = fmt.Sprintf("%v", v)
409
-			}
410
-		}
411
-
412
-		if err := writer.Write(rowData); err != nil {
413
-			result.Success = false
414
-			result.Error = fmt.Sprintf("Failed to write CSV row: %v", err)
415
-			result.Time = time.Since(startTime).String()
416
-			return result
417
-		}
418
-	}
419
-
420
-	if err := rows.Err(); err != nil {
421
-		result.Success = false
422
-		result.Error = fmt.Sprintf("Row iteration error: %v", err)
423
-		result.Time = time.Since(startTime).String()
424
-		return result
425
-	}
426
-
427
-	writer.Flush()
428
-	if err := writer.Error(); err != nil {
429
-		result.Success = false
430
-		result.Error = fmt.Sprintf("Failed to flush CSV: %v", err)
431
-		result.Time = time.Since(startTime).String()
432
-		return result
433
-	}
434
-
435
-	result.Success = true
436
-	result.Data = map[string]interface{}{
437
-		"csv":           csvBuilder.String(),
438
-		"count":         count,
439
-		"includeHeader": includeHeader,
440
-	}
441
-	result.Count = count
442
-	result.Time = time.Since(startTime).String()
443
-
444
-	return result
445
-}
446
-
447
-// ExecuteQueryCSVStream 流式返回CSV数据
448
-func QueryCSVStream(db *sqlx.DB, sql string, w io.Writer, includeHeader bool) (int, error) {
449
-
450
-	rows, err := db.Query(sql)
451
-	if err != nil {
452
-		return 0, err
453
-	}
454
-	defer rows.Close()
455
-
456
-	columns, err := rows.Columns()
457
-	if err != nil {
458
-		return 0, err
459
-	}
460
-
461
-	writer := csv.NewWriter(w)
462
-	count := 0
463
-
464
-	if includeHeader {
465
-		if err := writer.Write(columns); err != nil {
466
-			return 0, err
467
-		}
468
-	}
469
-
470
-	for rows.Next() {
471
-		count++
472
-
473
-		values := make([]interface{}, len(columns))
474
-		valuePtrs := make([]interface{}, len(columns))
475
-		for i := range columns {
476
-			valuePtrs[i] = &values[i]
477
-		}
478
-
479
-		if err := rows.Scan(valuePtrs...); err != nil {
480
-			return count, err
481
-		}
482
-
483
-		rowData := make([]string, len(columns))
484
-		for i, val := range values {
485
-			if val == nil {
486
-				rowData[i] = ""
487
-				continue
488
-			}
489
-			rowData[i] = fmt.Sprintf("%v", val)
490
-		}
491
-
492
-		if err := writer.Write(rowData); err != nil {
493
-			return count, err
494
-		}
495
-	}
496
-
497
-	writer.Flush()
498
-	if err := writer.Error(); err != nil {
499
-		return count, err
500
-	}
501
-
502
-	if err := rows.Err(); err != nil {
503
-		return count, err
504
-	}
505
-
506
-	return count, nil
507
-}

+ 114
- 0
functions/query_csv.go Просмотреть файл

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

+ 152
- 0
functions/query_json.go Просмотреть файл

@@ -0,0 +1,152 @@
1
+package functions
2
+
3
+import (
4
+	"database/sql"
5
+	"encoding/json"
6
+	"fmt"
7
+	"time"
8
+
9
+	"git.x2erp.com/qdy/go-base/types"
10
+	"github.com/jmoiron/sqlx"
11
+)
12
+
13
+// QueryParamsNameToJSON 执行带命名参数的查询
14
+func QueryParamsNameToJSON(db *sqlx.DB, sql string, params map[string]interface{}) *types.QueryResult {
15
+	startTime := time.Now()
16
+
17
+	if sql == "" {
18
+		return createErrorResult("SQL query cannot be empty", startTime)
19
+	}
20
+
21
+	// 处理命名参数
22
+	query, args, err := sqlx.Named(sql, params)
23
+	if err != nil {
24
+		return createErrorResult(fmt.Sprintf("Failed to process named parameters: %v", err), startTime)
25
+	}
26
+
27
+	// 执行查询
28
+	rows, err := db.Query(sqlx.Rebind(sqlx.DOLLAR, query), args...)
29
+	if err != nil {
30
+		return createErrorResult(fmt.Sprintf("Query execution failed: %v", err), startTime)
31
+	}
32
+	defer rows.Close()
33
+
34
+	// 处理结果集
35
+	return processQueryResult(rows, startTime)
36
+}
37
+
38
+// QueryPositionalToJSON 执行带位置参数的查询
39
+func QueryPositionalToJSON(db *sqlx.DB, sql string, params ...interface{}) *types.QueryResult {
40
+	startTime := time.Now()
41
+
42
+	if sql == "" {
43
+		return createErrorResult("SQL query cannot be empty", startTime)
44
+	}
45
+
46
+	// 执行查询
47
+	rows, err := db.Query(sql, params...)
48
+	if err != nil {
49
+		return createErrorResult(fmt.Sprintf("Query execution failed: %v", err), startTime)
50
+	}
51
+	defer rows.Close()
52
+
53
+	// 处理结果集
54
+	return processQueryResult(rows, startTime)
55
+}
56
+
57
+// QueryToJSON 执行无参数的查询
58
+func QueryToJSON(db *sqlx.DB, sql string) *types.QueryResult {
59
+	startTime := time.Now()
60
+
61
+	if sql == "" {
62
+		return createErrorResult("SQL query cannot be empty", startTime)
63
+	}
64
+
65
+	// 执行查询
66
+	rows, err := db.Query(sql)
67
+	if err != nil {
68
+		return createErrorResult(fmt.Sprintf("Query execution failed: %v", err), startTime)
69
+	}
70
+	defer rows.Close()
71
+
72
+	// 处理结果集
73
+	return processQueryResult(rows, startTime)
74
+}
75
+
76
+// processQueryResult 处理查询结果(公共部分)
77
+func processQueryResult(rows *sql.Rows, startTime time.Time) *types.QueryResult {
78
+	result := &types.QueryResult{}
79
+
80
+	// 获取列信息
81
+	columns, err := rows.Columns()
82
+	if err != nil {
83
+		result.Success = false
84
+		result.Error = fmt.Sprintf("Failed to get columns: %v", err)
85
+		result.Time = time.Since(startTime).String()
86
+		return result
87
+	}
88
+
89
+	var results []map[string]interface{}
90
+	count := 0
91
+
92
+	// 遍历所有行
93
+	for rows.Next() {
94
+		count++
95
+		values := make([]interface{}, len(columns))
96
+		valuePtrs := make([]interface{}, len(columns))
97
+		for i := range columns {
98
+			valuePtrs[i] = &values[i]
99
+		}
100
+
101
+		if err := rows.Scan(valuePtrs...); err != nil {
102
+			result.Success = false
103
+			result.Error = fmt.Sprintf("Failed to scan row: %v", err)
104
+			result.Time = time.Since(startTime).String()
105
+			return result
106
+		}
107
+
108
+		resultMap := make(map[string]interface{})
109
+		for i, col := range columns {
110
+			// 完全不处理类型,直接赋值,让 json.Marshal 自己处理
111
+			resultMap[col] = values[i]
112
+		}
113
+		results = append(results, resultMap)
114
+	}
115
+
116
+	// 检查行遍历错误
117
+	if err := rows.Err(); err != nil {
118
+		result.Success = false
119
+		result.Error = fmt.Sprintf("Row iteration error: %v", err)
120
+		result.Time = time.Since(startTime).String()
121
+		return result
122
+	}
123
+
124
+	// 转换为JSON
125
+	jsonData, err := json.Marshal(results)
126
+	if err != nil {
127
+		result.Success = false
128
+		result.Error = fmt.Sprintf("JSON marshal failed: %v", err)
129
+		result.Time = time.Since(startTime).String()
130
+		return result
131
+	}
132
+
133
+	// 构建成功结果
134
+	result.Success = true
135
+	result.Data = map[string]interface{}{
136
+		"json":  string(jsonData),
137
+		"rows":  results,
138
+		"count": count,
139
+	}
140
+	result.Count = count
141
+	result.Time = time.Since(startTime).String()
142
+	return result
143
+}
144
+
145
+// createErrorResult 创建错误结果的辅助函数
146
+func createErrorResult(errorMsg string, startTime time.Time) *types.QueryResult {
147
+	return &types.QueryResult{
148
+		Success: false,
149
+		Error:   errorMsg,
150
+		Time:    time.Since(startTime).String(),
151
+	}
152
+}

Загрузка…
Отмена
Сохранить