Explorar el Código

修改Doris提交格式-错误

qdy hace 3 meses
padre
commit
199d179572
Se han modificado 6 ficheros con 489 adiciones y 22 borrados
  1. 3
    2
      go.mod
  2. 23
    14
      go.sum
  3. 23
    6
      main.go
  4. 112
    0
      test/my1_test.go
  5. 92
    0
      test/my2_test.go
  6. 236
    0
      test/my_test.go

+ 3
- 2
go.mod Ver fichero

@@ -3,8 +3,8 @@ module git.x2erp.com/qdy/go-service-agent
3 3
 go 1.25.4
4 4
 
5 5
 require (
6
-	git.x2erp.com/qdy/go-base v0.1.10
7
-	git.x2erp.com/qdy/go-db v0.1.16
6
+	git.x2erp.com/qdy/go-base v0.1.11
7
+	git.x2erp.com/qdy/go-db v0.1.20
8 8
 	github.com/gin-gonic/gin v1.11.0
9 9
 )
10 10
 
@@ -21,6 +21,7 @@ require (
21 21
 	github.com/go-playground/universal-translator v0.18.1 // indirect
22 22
 	github.com/go-playground/validator/v10 v10.27.0 // indirect
23 23
 	github.com/go-redis/redis/v8 v8.11.5 // indirect
24
+	github.com/go-resty/resty/v2 v2.17.0 // indirect
24 25
 	github.com/go-sql-driver/mysql v1.9.3 // indirect
25 26
 	github.com/goccy/go-json v0.10.2 // indirect
26 27
 	github.com/goccy/go-yaml v1.18.0 // indirect

+ 23
- 14
go.sum Ver fichero

@@ -1,19 +1,13 @@
1 1
 filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
2 2
 filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
3
-git.x2erp.com/qdy/go-base v0.1.9 h1:SuyYSt3Gp7aXiUQRCBNwhrusJ53wlCnagiTYs5eITlY=
4
-git.x2erp.com/qdy/go-base v0.1.9/go.mod h1:Q+YLwpCoU8CVSnzATLdz2LAzVMlz/CEGzo8DePf7cug=
5
-git.x2erp.com/qdy/go-base v0.1.10 h1:qHvRNSBoQHZfYrXUpZ42r925OO7aT95tIZK/qh6Cd60=
6
-git.x2erp.com/qdy/go-base v0.1.10/go.mod h1:Q+YLwpCoU8CVSnzATLdz2LAzVMlz/CEGzo8DePf7cug=
7
-git.x2erp.com/qdy/go-db v0.1.11 h1:dT22aYhtfk+Y3q2/jc8UZSuCjsLFC/eBrwwTHDUTOsA=
8
-git.x2erp.com/qdy/go-db v0.1.11/go.mod h1:6dICJn/sZRj0WIMf5y8MfsjBC1wWZcG4lczgeIAGBhM=
9
-git.x2erp.com/qdy/go-db v0.1.12 h1:z4VfTbIMNhBbpPmjRRtSjEkXet7nvVRjTd92+IFsGbw=
10
-git.x2erp.com/qdy/go-db v0.1.12/go.mod h1:tcHV7sqEFYWbL/196NZxVnbdHevefRppggMTARVXQtE=
11
-git.x2erp.com/qdy/go-db v0.1.13 h1:gx1Ld+b3QRaO7VvyBm4fipafGkl0Yl+4ERzromAtck4=
12
-git.x2erp.com/qdy/go-db v0.1.13/go.mod h1:tcHV7sqEFYWbL/196NZxVnbdHevefRppggMTARVXQtE=
13
-git.x2erp.com/qdy/go-db v0.1.15 h1:YvwT/FyrvQQodzggGLyxlSQu++f7+NHDvkUR7tuDVfY=
14
-git.x2erp.com/qdy/go-db v0.1.15/go.mod h1:5dnPmDEOhfuKtV1anuSibSNibTINul6/qdRxH1khQ8k=
15
-git.x2erp.com/qdy/go-db v0.1.16 h1:un5FMemqX6jSDdp6N2+7Elw73iC9zUH5r8UlX+JZfak=
16
-git.x2erp.com/qdy/go-db v0.1.16/go.mod h1:OrWk/iWygMEWsB7Rzdu7VjPszyEog8bodLx+X+5nWxE=
3
+git.x2erp.com/qdy/go-base v0.1.11 h1:STHT6z+zaN8kMIiXfggUdPaP4vcz+kpXaxHkw5ziXzA=
4
+git.x2erp.com/qdy/go-base v0.1.11/go.mod h1:Q+YLwpCoU8CVSnzATLdz2LAzVMlz/CEGzo8DePf7cug=
5
+git.x2erp.com/qdy/go-db v0.1.18 h1:jCNRCZpFuW1eN769R91YW49B+24Xl9t4qzS3Wtt6V40=
6
+git.x2erp.com/qdy/go-db v0.1.18/go.mod h1:BpoceA0ROuIp6N2aOplVNWKrwntDQeWGF63diEd1hp4=
7
+git.x2erp.com/qdy/go-db v0.1.19 h1:ydKKsu9XoZBYkJo81bat1IQuKnZVc7xpD/qahI1BSRE=
8
+git.x2erp.com/qdy/go-db v0.1.19/go.mod h1:BpoceA0ROuIp6N2aOplVNWKrwntDQeWGF63diEd1hp4=
9
+git.x2erp.com/qdy/go-db v0.1.20 h1:6+esB8b/KzF6WAKRe6lWIwUZqX/tPbqgBYJhpYW3uhc=
10
+git.x2erp.com/qdy/go-db v0.1.20/go.mod h1:BpoceA0ROuIp6N2aOplVNWKrwntDQeWGF63diEd1hp4=
17 11
 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U=
18 12
 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM=
19 13
 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.10.1 h1:B+blDbyVIG3WaikNxPnhPiJ1MThR03b3vKGtER95TP4=
@@ -39,6 +33,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
39 33
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
40 34
 github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
41 35
 github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
36
+github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
37
+github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
42 38
 github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
43 39
 github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
44 40
 github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
@@ -55,6 +51,8 @@ github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHO
55 51
 github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
56 52
 github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
57 53
 github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
54
+github.com/go-resty/resty/v2 v2.17.0 h1:pW9DeXcaL4Rrym4EZ8v7L19zZiIlWPg5YXAcVmt+gN0=
55
+github.com/go-resty/resty/v2 v2.17.0/go.mod h1:kCKZ3wWmwJaNc7S29BRtUhJwy7iqmn+2mLtQrOyQlVA=
58 56
 github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
59 57
 github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
60 58
 github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
@@ -87,6 +85,7 @@ github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
87 85
 github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
88 86
 github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
89 87
 github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
88
+github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
90 89
 github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
91 90
 github.com/microsoft/go-mssqldb v1.9.4 h1:sHrj3GcdgkxytZ09aZ3+ys72pMeyEXJowT44j74pNgs=
92 91
 github.com/microsoft/go-mssqldb v1.9.4/go.mod h1:GBbW9ASTiDC+mpgWDGKdm3FnFLTUsLYN3iFL90lQ+PA=
@@ -94,6 +93,12 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OH
94 93
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
95 94
 github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
96 95
 github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
96
+github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
97
+github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
98
+github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
99
+github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
100
+github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
101
+github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
97 102
 github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
98 103
 github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
99 104
 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
@@ -136,12 +141,16 @@ golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
136 141
 golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
137 142
 golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
138 143
 golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
144
+golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
145
+golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
139 146
 golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
140 147
 golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
141 148
 google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
142 149
 google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
143 150
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
144 151
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
152
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
153
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
145 154
 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
146 155
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
147 156
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

+ 23
- 6
main.go Ver fichero

@@ -4,7 +4,10 @@ import (
4 4
 	"fmt"
5 5
 	"log"
6 6
 	"net/http"
7
+	"os"
8
+	"os/signal"
7 9
 	"strings"
10
+	"syscall"
8 11
 	"time"
9 12
 
10 13
 	"git.x2erp.com/qdy/go-base/config"
@@ -45,6 +48,12 @@ func startHTTPServer() {
45 48
 	if err != nil {
46 49
 		log.Fatalf("Failed to create DB factory: %v", err)
47 50
 	}
51
+	// 设置优雅关闭
52
+	setupGracefulShutdown(dbFactory)
53
+	defer func() {
54
+		dbFactory.Close()
55
+		log.Println("Database connection closed")
56
+	}()
48 57
 
49 58
 	// 核心路由
50 59
 	router.GET("/api/health", functions.HealthHandler(dbFactory, cfg.GetDatabase().Type))
@@ -62,12 +71,6 @@ func startHTTPServer() {
62 71
 	// 设置可信代理
63 72
 	setupTrustedProxies(router, serviceConfig.TrustedProxies)
64 73
 
65
-	// 启动服务
66
-	log.Println("POST /api/query  - Execute SQL query to JSON")
67
-	log.Println("POST /api/query/csv  - Execute SQL query to CSV")
68
-	log.Println("GET  /api/health - Health check")
69
-	log.Println("GET  /api/info   - Database info")
70
-
71 74
 	// 创建HTTP服务器配置
72 75
 	server := &http.Server{
73 76
 		Addr:         fmt.Sprintf(":%d", serviceConfig.Port),
@@ -81,6 +84,7 @@ func startHTTPServer() {
81 84
 	if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
82 85
 		log.Fatalf("Failed to start server: %v", err)
83 86
 	}
87
+
84 88
 }
85 89
 
86 90
 // 参数绑定包装器
@@ -135,3 +139,16 @@ func setupTrustedProxiesRouter(router *gin.Engine, trimmedProxies []string) {
135 139
 	}
136 140
 
137 141
 }
142
+
143
+func setupGracefulShutdown(dbFactory *factory.DBFactory) {
144
+	signalCh := make(chan os.Signal, 1)
145
+	signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM)
146
+
147
+	go func() {
148
+		<-signalCh
149
+		log.Println("\nReceived shutdown signal, closing database connection...")
150
+		dbFactory.Close()
151
+		log.Println("Database connection closed gracefully")
152
+		os.Exit(0)
153
+	}()
154
+}

+ 112
- 0
test/my1_test.go Ver fichero

@@ -0,0 +1,112 @@
1
+package main
2
+
3
+import (
4
+	"encoding/json"
5
+	"fmt"
6
+	"io"
7
+	"net/http"
8
+	"strings"
9
+	"testing"
10
+	"time"
11
+)
12
+
13
+// Doris Stream Load响应结构
14
+type DorisResponse struct {
15
+	TxnID            int    `json:"TxnId"`
16
+	Label            string `json:"Label"`
17
+	Status           string `json:"Status"`
18
+	Message          string `json:"Message"`
19
+	NumberTotalRows  int    `json:"NumberTotalRows"`
20
+	NumberLoadedRows int    `json:"NumberLoadedRows"`
21
+	LoadBytes        int    `json:"LoadBytes"`
22
+	ErrorURL         string `json:"ErrorURL"`
23
+}
24
+
25
+func insertToDorisDirect(csvData string) error {
26
+	url := "http://161.189.89.196:8040/api/X6_STOCK_DEV/A3_CLOTHING_LOG/_stream_load"
27
+	username := "root"
28
+	password := "mos8555"
29
+
30
+	fmt.Printf("=== Doris Stream Load测试 ===\n")
31
+	fmt.Printf("URL: %s\n", url)
32
+	fmt.Printf("数据: %s\n", csvData)
33
+
34
+	// 创建PUT请求
35
+	req, err := http.NewRequest("PUT", url, strings.NewReader(csvData))
36
+	if err != nil {
37
+		return fmt.Errorf("创建请求失败: %v", err)
38
+	}
39
+
40
+	// 设置Basic Auth
41
+	req.SetBasicAuth(username, password)
42
+
43
+	// 设置headers - 与curl命令保持一致
44
+	req.Header.Set("Expect", "100-continue")
45
+	req.Header.Set("column_separator", ",")
46
+	req.Header.Set("enclose", "\"")
47
+
48
+	// 设置唯一的label用于追踪
49
+	label := fmt.Sprintf("test_%d", time.Now().UnixNano())
50
+	req.Header.Set("label", label)
51
+
52
+	// 创建HTTP客户端,允许自动重定向
53
+	client := &http.Client{
54
+		Timeout: 30 * time.Second,
55
+	}
56
+
57
+	// 发送请求
58
+	fmt.Println("发送请求到Doris...")
59
+	resp, err := client.Do(req)
60
+	if err != nil {
61
+		return fmt.Errorf("请求失败: %v", err)
62
+	}
63
+	defer resp.Body.Close()
64
+
65
+	// 处理响应
66
+	body, err := io.ReadAll(resp.Body)
67
+	if err != nil {
68
+		return fmt.Errorf("读取响应失败: %v", err)
69
+	}
70
+
71
+	responseBody := string(body)
72
+	fmt.Printf("HTTP状态码: %d\n", resp.StatusCode)
73
+	fmt.Printf("响应内容: %s\n", responseBody)
74
+
75
+	// 解析JSON响应
76
+	var dorisResp DorisResponse
77
+	if err := json.Unmarshal(body, &dorisResp); err != nil {
78
+		return fmt.Errorf("解析响应失败: %v, 原始响应: %s", err, responseBody)
79
+	}
80
+
81
+	// 检查处理状态 - 修正状态检查逻辑
82
+	if dorisResp.Status == "FAIL" {
83
+		return fmt.Errorf("Stream Load失败: %s (TxnID: %d)", dorisResp.Message, dorisResp.TxnID)
84
+	}
85
+
86
+	// 修正:Doris返回的状态可能是 "Success" 而不是 "SUCCESS"
87
+	if strings.ToUpper(dorisResp.Status) != "SUCCESS" {
88
+		return fmt.Errorf("未知状态: %s, 消息: %s", dorisResp.Status, dorisResp.Message)
89
+	}
90
+
91
+	fmt.Printf("✅ Stream Load成功! \n")
92
+	fmt.Printf("   TxnID: %d\n", dorisResp.TxnID)
93
+	fmt.Printf("   Label: %s\n", dorisResp.Label)
94
+	fmt.Printf("   加载行数: %d/%d\n", dorisResp.NumberLoadedRows, dorisResp.NumberTotalRows)
95
+	fmt.Printf("   数据大小: %d bytes\n", dorisResp.LoadBytes)
96
+
97
+	return nil
98
+}
99
+
100
+// 测试函数
101
+func TestDorisStreamLoad(t *testing.T) {
102
+	fmt.Println("=== 测试Doris Stream Load ===")
103
+
104
+	csvData := "EWE322Y20600491-03,2021,H-大部分"
105
+
106
+	err := insertToDorisDirect(csvData)
107
+	if err != nil {
108
+		t.Fatalf("Stream Load失败: %v", err)
109
+	}
110
+
111
+	fmt.Println("✅ 数据成功插入Doris!")
112
+}

+ 92
- 0
test/my2_test.go Ver fichero

@@ -0,0 +1,92 @@
1
+package main
2
+
3
+import (
4
+	"database/sql"
5
+	"fmt"
6
+	"testing"
7
+
8
+	_ "github.com/go-sql-driver/mysql"
9
+)
10
+
11
+// 使用MySQL协议插入数据
12
+func insertViaMySQL() error {
13
+	// Doris MySQL连接信息
14
+	dsn := "root:mos8555@tcp(161.189.89.196:9030)/X6_STOCK_DEV"
15
+
16
+	db, err := sql.Open("mysql", dsn)
17
+	if err != nil {
18
+		return fmt.Errorf("连接数据库失败: %v", err)
19
+	}
20
+	defer db.Close()
21
+
22
+	// 测试连接
23
+	err = db.Ping()
24
+	if err != nil {
25
+		return fmt.Errorf("数据库连接测试失败: %v", err)
26
+	}
27
+
28
+	fmt.Println("✅ 成功连接到Doris MySQL")
29
+
30
+	// 插入数据
31
+	query := "INSERT INTO A3_CLOTHING (col1, col2, col3) VALUES (?, ?, ?)"
32
+	result, err := db.Exec(query, "EWE322Y2060049145", 2021, "Y-连衣裙")
33
+	if err != nil {
34
+		return fmt.Errorf("插入数据失败: %v", err)
35
+	}
36
+
37
+	rowsAffected, err := result.RowsAffected()
38
+	if err != nil {
39
+		return fmt.Errorf("获取影响行数失败: %v", err)
40
+	}
41
+
42
+	fmt.Printf("✅ 数据插入成功,影响行数: %d\n", rowsAffected)
43
+	return nil
44
+}
45
+
46
+// 先检查表结构
47
+func checkTableSchema() error {
48
+	dsn := "root:mos8555@tcp(161.189.89.196:9030)/X6_STOCK_DEV"
49
+	db, err := sql.Open("mysql", dsn)
50
+	if err != nil {
51
+		return err
52
+	}
53
+	defer db.Close()
54
+
55
+	// 查询表结构
56
+	rows, err := db.Query("DESC A3_CLOTHING")
57
+	if err != nil {
58
+		return fmt.Errorf("查询表结构失败: %v", err)
59
+	}
60
+	defer rows.Close()
61
+
62
+	fmt.Println("=== A3_CLOTHING 表结构 ===")
63
+	for rows.Next() {
64
+		var field, fieldType, isNull, key, defaultValue, extra string
65
+		err := rows.Scan(&field, &fieldType, &isNull, &key, &defaultValue, &extra)
66
+		if err != nil {
67
+			return err
68
+		}
69
+		fmt.Printf("字段: %s, 类型: %s, 允许空: %s\n", field, fieldType, isNull)
70
+	}
71
+
72
+	return nil
73
+}
74
+
75
+// 测试函数
76
+func TestMySQLInsert(t *testing.T) {
77
+	fmt.Println("=== 使用MySQL协议插入数据 ===")
78
+
79
+	// 先检查表结构
80
+	err := checkTableSchema()
81
+	if err != nil {
82
+		t.Fatalf("检查表结构失败: %v", err)
83
+	}
84
+
85
+	// 插入数据
86
+	err = insertViaMySQL()
87
+	if err != nil {
88
+		t.Fatalf("MySQL插入失败: %v", err)
89
+	}
90
+
91
+	fmt.Println("✅ 通过MySQL协议插入数据成功!")
92
+}

+ 236
- 0
test/my_test.go Ver fichero

@@ -0,0 +1,236 @@
1
+package main
2
+
3
+import (
4
+	"fmt"
5
+	"testing"
6
+	"time"
7
+
8
+	"git.x2erp.com/qdy/go-base/config"
9
+	"git.x2erp.com/qdy/go-db/factory"
10
+)
11
+
12
+// QueryRequest 查询请求结构体
13
+type QueryRequest struct {
14
+	SQL string `json:"sql"`
15
+}
16
+
17
+func TestQueryAndInsertToDoris(t *testing.T) {
18
+	// 记录总开始时间
19
+	totalStartTime := time.Now()
20
+	// 1. 获取HTTP工厂实例
21
+	httpFactory, err := factory.GetHTTPFactory()
22
+	if err != nil {
23
+		t.Fatalf("Failed to get HTTP factory: %v", err)
24
+	}
25
+	fmt.Println("HTTP factory created successfully")
26
+
27
+	// 2. 创建HTTP客户端
28
+	httpClient := httpFactory.CreateClient()
29
+
30
+	// 3. 准备查询SQL - 限制数据量用于测试
31
+	querySQL := getSQL()
32
+
33
+	// 4. 准备查询请求
34
+	queryRequest := QueryRequest{
35
+		SQL: querySQL,
36
+	}
37
+
38
+	// 记录查询开始时间
39
+	queryStartTime := time.Now()
40
+	// 5. 发送POST请求到 /api/query/csv 获取CSV格式数据
41
+	fmt.Println("Sending query request to localhost:8080/api/query/csv...")
42
+
43
+	resp, err := httpClient.PostWithAuth(
44
+		"http://localhost:8080/api/query/csv",
45
+		queryRequest,
46
+		"123", // Bearer Token
47
+		nil,
48
+	)
49
+
50
+	if err != nil {
51
+		t.Fatalf("Failed to send query request: %v", err)
52
+	}
53
+
54
+	if resp.StatusCode() != 200 {
55
+		t.Fatalf("Query request failed with status: %d, body: %s", resp.StatusCode(), string(resp.Body()))
56
+	}
57
+
58
+	// 6. 获取CSV数据
59
+	csvData := string(resp.Body())
60
+	if len(csvData) == 0 {
61
+		t.Fatalf("No CSV data received")
62
+	}
63
+
64
+	// 记录查询结束时间
65
+	queryEndTime := time.Now()
66
+	queryDuration := queryEndTime.Sub(queryStartTime)
67
+
68
+	fmt.Printf("✅ Query completed in %v\n", queryDuration)
69
+	fmt.Printf("Successfully retrieved CSV data, length: %d bytes\n", len(csvData))
70
+	//fmt.Printf("CSV data content:\n%s\n", csvData)
71
+
72
+	// 7. 获取Doris工厂实例
73
+	dorisFactory, err := factory.GetDorisFactory(httpFactory)
74
+	if err != nil {
75
+		t.Fatalf("Failed to get Doris factory: %v", err)
76
+	}
77
+	fmt.Println("Doris factory created successfully")
78
+
79
+	// 8. 先检查Doris表结构
80
+	fmt.Println("Checking Doris table structure...")
81
+
82
+	// 9. 插入数据到Doris
83
+	database := "X6_STOCK_DEV"
84
+	table := "A3_CLOTHING"
85
+	skipHeader := false // 改为true,跳过CSV头行
86
+
87
+	fmt.Printf("Inserting data to Doris database: %s, table: %s\n", database, table)
88
+	//fmt.Printf("CSV data to insert:\n%q\n", csvData)
89
+
90
+	cfg := config.GetConfig()
91
+	url := fmt.Sprintf("http://%s:%d/api/%s/%s/_stream_load", cfg.GetDoris().FEHost, cfg.GetDoris().FEPort, database, table)
92
+
93
+	fmt.Print(url + ".\n")
94
+
95
+	// 记录保存开始时间
96
+	saveStartTime := time.Now()
97
+	err = dorisFactory.InsertCSV(database, table, csvData, skipHeader)
98
+	if err != nil {
99
+		t.Fatalf("Failed to insert data to Doris: %v", err)
100
+	}
101
+
102
+	// 记录保存结束时间
103
+	saveEndTime := time.Now()
104
+	saveDuration := saveEndTime.Sub(saveStartTime)
105
+
106
+	fmt.Printf("✅ Data saved to Doris in %v\n", saveDuration)
107
+
108
+	// 记录总结束时间
109
+	totalEndTime := time.Now()
110
+	totalDuration := totalEndTime.Sub(totalStartTime)
111
+
112
+	// 打印性能统计
113
+	fmt.Println("\n📊 Performance Statistics:")
114
+	fmt.Printf("   Query Time: %v\n", queryDuration)
115
+	fmt.Printf("   Save Time:  %v\n", saveDuration)
116
+	fmt.Printf("   Total Time: %v\n", totalDuration)
117
+	fmt.Printf("   Data Size:  %d bytes\n", len(csvData))
118
+
119
+	fmt.Println("Data successfully inserted to Doris!")
120
+}
121
+
122
+func getSQLm() string {
123
+	return `SELECT
124
+    CLOTHING_ID,
125
+    CLOTHING_YEAR,
126
+    CLOTHING_NAME
127
+FROM X6_STOCK_DEV.A3_CLOTHING WHERE rownum <= 100000`
128
+}
129
+
130
+func getSQL() string {
131
+	// 3. 准备查询SQL
132
+	return `SELECT
133
+    CLOTHING_ID,
134
+    CLOTHING_YEAR,
135
+    CLOTHING_NAME,
136
+    STYLECOLOR_ID,
137
+    STYLE_ID,
138
+    COLOR_ID,
139
+    SIZE_ID,
140
+    CREATE_DATE,
141
+    STYLE_GROUP,
142
+    J_PRICE,
143
+    X_PRICE,
144
+    V_PRICE,
145
+    CLERK_ROYALTYRATE,
146
+    CLERK_ROYALTYPRICE,
147
+    BRAND_CODE,
148
+    STYLEVER_ID,
149
+    J_COST,
150
+    CLOTHING_IMG,
151
+    STYLE_UNIT_CODE,
152
+    STYLE_SEX_CODE,
153
+    STYLE_KIND_CODE,
154
+    STYLE_CLASS_CODE,
155
+    STYLE_SUBCLASS_CODE,
156
+    STYLE_DESIGNER_CODE,
157
+    STYLE_PLATER_CODE,
158
+    STYLE_STYLES_CODE,
159
+    STYLE_LOCATE_CODE,
160
+    STYLE_SALETYPE_CODE,
161
+    STYLE_COLORSYSTEM_CODE,
162
+    STYLE_THEME_CODE,
163
+    STYLE_INDENTTYPE_CODE,
164
+    STYLE_PRICEBAND_CODE,
165
+    STYLE_MONTH_CODE,
166
+    STYLE_COMPOSITION_CODE,
167
+    STYLE_SUPPLIER_CODE,
168
+    STYLE_SPARE1_CODE,
169
+    STYLE_SPARE2_CODE,
170
+    STYLE_SPARE4_CODE,
171
+    STYLE_SPARE5_CODE,
172
+    CATEGORY_CODE,
173
+    BRAND_ID,
174
+    STYCOLVER_ID,
175
+    STYLE_SAME,
176
+    CLOTHING_BARCODE,
177
+    CLOTHING_HELPID,
178
+    CLOTHING_GBCODE,
179
+    CLOTHING_RFID,
180
+    STYLE_SUBJECT_ID,
181
+    SIZEGRP_ID,
182
+    STYLE_HELPID,
183
+    CLOTHING_GBCODE1,
184
+    COLOR_NAME,
185
+    STYLEVER_NAME,
186
+    SIZE_NAME,
187
+    STYLE_UNIT,
188
+    STYLE_SEX,
189
+    STYLE_KIND,
190
+    STYLE_CLASS,
191
+    STYLE_SUBCLASS,
192
+    STYLE_DESIGNER,
193
+    STYLE_PLATER,
194
+    STYLE_BAND,
195
+    STYLE_STYLES,
196
+    STYLE_LOCATE,
197
+    STYLE_SALETYPE,
198
+    STYLE_COLORSYSTEM,
199
+    STYLE_THEME,
200
+    STYLE_INDENTTYPE,
201
+    STYLE_PRICEBAND,
202
+    STYLE_MONTH,
203
+    STYLE_COMPOSITION,
204
+    STYLE_SUPPLIER,
205
+    STYLE_SPARE1,
206
+    STYLE_SPARE2,
207
+    STYLE_SPARE3,
208
+    STYLE_SPARE4,
209
+    STYLE_SPARE5,
210
+    CATEGORY_NAME,
211
+    BRAND_NAME,
212
+    STYLE_YEAR_NAME,
213
+    STYLE_SEARCH_KEY,
214
+    STYLE_SUBJECT_NAME,
215
+    CLOTHING_REMARK,
216
+    STYLE_SPARE3_CODE,
217
+    COST,
218
+    BRAND_GROUPCODE,
219
+    CLASS_GROUPCODE,
220
+    MONTH_GROUPCODE,
221
+    RETURNSUBJECT_ID,
222
+    PRODUCT_SORT,
223
+    CLOTHING_PARTITION
224
+   FROM (
225
+    SELECT a.*, ROWNUM as rn
226
+    FROM (
227
+        SELECT *
228
+        FROM X6_STOCK_DEV.A3_CLOTHING 
229
+        ORDER BY CLOTHING_ID
230
+    ) a
231
+    WHERE ROWNUM <= 41000 
232
+)
233
+WHERE rn > 39000`
234
+
235
+	// FROM X6_STOCK_DEV.A3_CLOTHING WHERE rownum > 100 and rownum <= 20000`
236
+}

Loading…
Cancelar
Guardar