xugusql_connector.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. package xugu
  2. import (
  3. "context"
  4. "database/sql/driver"
  5. "fmt"
  6. "net"
  7. "strings"
  8. "time"
  9. )
  10. // SQL类型常量
  11. const (
  12. SQL_UNKNOWN = iota
  13. SQL_SELECT
  14. SQL_INSERT
  15. SQL_UPDATE
  16. SQL_DELETE
  17. SQL_CREATE
  18. SQL_ALTER
  19. SQL_PROCEDURE
  20. SQL_OTHER
  21. )
  22. const (
  23. XG_OK = iota
  24. )
  25. const (
  26. ERROR_BUFF_SIZE uint = 1024
  27. PREPARE_NAME_BUFF_SIZE uint = 128
  28. CURSOR_NAME_BUFF_SIZE uint = 128
  29. ROWID_BUFF_SIZE uint = 256
  30. COLUMN_NAME_BUFF_SIZE uint = 256
  31. FIELD_BUFF_SIZE uint = 4096
  32. LOB_BUFF_SIZE uint = 8
  33. RET_NO_DATA int = 100
  34. // SQL_UNKNOWN int = 0
  35. // SQL_SELECT int = 4
  36. // SQL_CREATE int = 5
  37. // SQL_PROCEDURE int = 10
  38. SQL_PARAM_INPUT int = 1
  39. SQL_PARAM_OUTPUT int = 2
  40. SQL_PARAM_INPUTOUTPUT int = 3
  41. SQL_PARAM_RETURNVALUE int = 6
  42. SQL_XG_C_CHAR int = 2
  43. SQL_XG_C_CLOB int = 41
  44. SQL_XG_C_BLOB int = 42
  45. SQL_XG_C_NULL int = -11
  46. BIND_PARAM_BY_NAME int = 62
  47. BIND_PARAM_BY_POS int = 63
  48. )
  49. type connector struct {
  50. dsn string
  51. }
  52. // func NewConnector(dsn string) *connector {
  53. // dsnL := strings.ToLower(dsn)
  54. // fmt.Println("dsnL: ", dsnL)
  55. // return &connector{dsn: dsnL}
  56. // }
  57. var IPS_COUNTER int = 0
  58. // Driver implements driver.Connector interface.
  59. // Driver returns &XuguDriver{}
  60. func (self *connector) Driver() driver.Driver {
  61. return &XuguDriver{}
  62. }
  63. // Connect implements driver.Connector interface.
  64. // Connect returns a connection to the database.
  65. func (self *connector) Connect(ctx context.Context) (driver.Conn, error) {
  66. obj := &xugusqlConn{conn: nil}
  67. //connKeyValue := C.CString(self.dsn)
  68. dsnConfig := parseDSN(self.dsn)
  69. fmt.Println("self.dsn:", strings.ToLower(self.dsn))
  70. obj.dsnConfig = dsnConfig
  71. fmt.Println("connector: ", self.dsn)
  72. fmt.Println("dsnConfig: ", dsnConfig)
  73. defer func() {
  74. // cgo_c_free(unsafe.Pointer(connKeyValue))
  75. }()
  76. re, _ := xg_connect(ctx, obj)
  77. if re < 0 {
  78. return nil, obj.get_error()
  79. // pos := strings.Index(strings.ToUpper(self.dsn), "IPS=")
  80. // if pos != -1 {
  81. // IPS_COUNTER++
  82. // re := xgc_connect_ips(ctx, &self.dsn, &obj.conn)
  83. // if re < 0 {
  84. // return nil, obj.get_error()
  85. // }
  86. // } else {
  87. // re, _ := xgc_connect(ctx, self.dsn, &obj.conn)
  88. // if re < 0 {
  89. // return nil, obj.get_error()
  90. // }
  91. }
  92. return obj, nil
  93. }
  94. func xg_connect(ctx context.Context, __pConn *xugusqlConn) (int, error) {
  95. return xgSockOpenConn(ctx, __pConn)
  96. }
  97. // ips未实现
  98. func xg_connect_ips(ctx context.Context, __pConn *net.Conn) int {
  99. return 0
  100. }
  101. func xgSockOpenConn(ctx context.Context, __pConn *xugusqlConn) (int, error) {
  102. fmt.Println("XGSOpenConn")
  103. nd := net.Dialer{Timeout: 5 * time.Second}
  104. netConn, err := nd.DialContext(ctx, "tcp", fmt.Sprintf("%s:%s", __pConn.IP, __pConn.Port))
  105. if err != nil {
  106. fmt.Println("tcp", err)
  107. return -8, err
  108. }
  109. // 启用 TCP 保活
  110. if tc, ok := netConn.(*net.TCPConn); ok {
  111. if err := tc.SetKeepAlive(true); err != nil {
  112. //c.cfg.Logger.Print(err) // 如果设置保活失败,记录错误但不终止
  113. }
  114. }
  115. //发送
  116. //fmt.Printf("login database = '%s' user = '%s' password = '%s' version='201' ", __pConn.Database, __pConn.User, __pConn.Password)
  117. // message := "login database = 'SYSTEM' user = 'SYSDBA' password = 'SYSDBA' version='201' "
  118. dsnMessage := generateLoginString(__pConn.dsnConfig)
  119. _, err = netConn.Write([]byte(dsnMessage))
  120. if err != nil {
  121. fmt.Println("发送数据失败:", err)
  122. }
  123. fmt.Println("数据已发送:", dsnMessage)
  124. buffer := make([]byte, 1024)
  125. n, err := __pConn.conn.Read(buffer)
  126. if err != nil {
  127. fmt.Println("Error reading from server:", err)
  128. }
  129. fmt.Println("Message from server:", string(buffer[:n]))
  130. return 1, nil
  131. }
  132. func parseDSN(dsn string) dsnConfig {
  133. // Initialize a dsnConfig struct
  134. var config dsnConfig
  135. // Split the string by semicolons
  136. pairs := strings.Split(dsn, ";")
  137. // Iterate over the pairs and map them to the struct fields
  138. for _, pair := range pairs {
  139. // Split each pair by the equals sign
  140. kv := strings.SplitN(pair, "=", 2)
  141. if len(kv) != 2 {
  142. continue
  143. }
  144. key, value := strings.TrimSpace(kv[0]), strings.Trim(strings.TrimSpace(kv[1]), "'")
  145. keyL := strings.ToLower(key)
  146. // Map the key to the appropriate struct field
  147. switch keyL {
  148. case "ip":
  149. config.IP = value
  150. case "port":
  151. config.Port = value
  152. case "db":
  153. config.Database = value
  154. case "user":
  155. config.User = value
  156. case "pwd":
  157. config.Password = value
  158. case "encryptor":
  159. config.Encryptor = value
  160. case "char_set":
  161. config.CharSet = value
  162. case "time_zone":
  163. config.TimeZone = value
  164. case "iso_level":
  165. config.IsoLevel = value
  166. case "lock_timeout":
  167. config.LockTimeout = value
  168. case "auto_commit":
  169. config.AutoCommit = value
  170. case "strict_commit":
  171. config.StrictCommit = value
  172. case "result":
  173. config.Result = value
  174. case "return_schema":
  175. config.ReturnSchema = value
  176. case "return_cursor_id":
  177. config.ReturnCursorID = value
  178. case "lob_ret":
  179. config.LobRet = value
  180. case "return_rowid":
  181. config.ReturnRowid = value
  182. case "version":
  183. config.Version = value
  184. }
  185. }
  186. return config
  187. }
  188. func generateLoginString(config dsnConfig) string {
  189. baseString := "login database = '%s' user = '%s' password = '%s' "
  190. additionalParams := ""
  191. if config.Encryptor != "" {
  192. additionalParams += fmt.Sprintf(" encryptor='%s'", config.Encryptor)
  193. }
  194. if config.CharSet != "" {
  195. additionalParams += fmt.Sprintf(" char_set='%s'", config.CharSet)
  196. }
  197. if config.TimeZone != "" {
  198. additionalParams += fmt.Sprintf(" time_zone='%s'", config.TimeZone)
  199. }
  200. if config.IsoLevel != "" {
  201. additionalParams += fmt.Sprintf(" iso_level='%s'", config.IsoLevel)
  202. }
  203. if config.LockTimeout != "" {
  204. additionalParams += fmt.Sprintf(" lock_timeout='%s'", config.LockTimeout)
  205. }
  206. if config.AutoCommit != "" {
  207. additionalParams += fmt.Sprintf(" auto_commit='%s'", config.AutoCommit)
  208. }
  209. if config.StrictCommit != "" {
  210. additionalParams += fmt.Sprintf(" strict_commit='%s'", config.StrictCommit)
  211. }
  212. if config.Result != "" {
  213. additionalParams += fmt.Sprintf(" result='%s'", config.Result)
  214. }
  215. if config.ReturnSchema != "" {
  216. additionalParams += fmt.Sprintf(" return_schema='%s'", config.ReturnSchema)
  217. }
  218. if config.ReturnCursorID != "" {
  219. additionalParams += fmt.Sprintf(" return_cursor_id='%s'", config.ReturnCursorID)
  220. }
  221. if config.LobRet != "" {
  222. additionalParams += fmt.Sprintf(" lob_ret='%s'", config.LobRet)
  223. }
  224. if config.ReturnRowid != "" {
  225. additionalParams += fmt.Sprintf(" return_rowid='%s'", config.ReturnRowid)
  226. }
  227. if config.Version != "" {
  228. additionalParams += fmt.Sprintf(" version='%s'", config.Version)
  229. } else {
  230. additionalParams += " version='201'"
  231. }
  232. finalString := fmt.Sprintf(baseString, config.Database, config.User, config.Password)
  233. if additionalParams != "" {
  234. finalString += additionalParams
  235. }
  236. //finalString += " version='201'"
  237. return finalString
  238. }