|
@@ -3,19 +3,67 @@ package xugu
|
|
import (
|
|
import (
|
|
"context"
|
|
"context"
|
|
"database/sql/driver"
|
|
"database/sql/driver"
|
|
- "errors"
|
|
|
|
"fmt"
|
|
"fmt"
|
|
"net"
|
|
"net"
|
|
|
|
+ "strings"
|
|
"time"
|
|
"time"
|
|
)
|
|
)
|
|
|
|
|
|
|
|
+// SQL类型常量
|
|
|
|
+const (
|
|
|
|
+ SQL_UNKNOWN = iota
|
|
|
|
+ SQL_SELECT
|
|
|
|
+ SQL_INSERT
|
|
|
|
+ SQL_UPDATE
|
|
|
|
+ SQL_DELETE
|
|
|
|
+ SQL_CREATE
|
|
|
|
+ SQL_ALTER
|
|
|
|
+ SQL_PROCEDURE
|
|
|
|
+ SQL_OTHER
|
|
|
|
+)
|
|
|
|
+const (
|
|
|
|
+ XG_OK = iota
|
|
|
|
+)
|
|
|
|
+
|
|
|
|
+const (
|
|
|
|
+ ERROR_BUFF_SIZE uint = 1024
|
|
|
|
+ PREPARE_NAME_BUFF_SIZE uint = 128
|
|
|
|
+ CURSOR_NAME_BUFF_SIZE uint = 128
|
|
|
|
+ ROWID_BUFF_SIZE uint = 256
|
|
|
|
+ COLUMN_NAME_BUFF_SIZE uint = 256
|
|
|
|
+
|
|
|
|
+ FIELD_BUFF_SIZE uint = 4096
|
|
|
|
+ LOB_BUFF_SIZE uint = 8
|
|
|
|
+ RET_NO_DATA int = 100
|
|
|
|
+
|
|
|
|
+ // SQL_UNKNOWN int = 0
|
|
|
|
+ // SQL_SELECT int = 4
|
|
|
|
+ // SQL_CREATE int = 5
|
|
|
|
+ // SQL_PROCEDURE int = 10
|
|
|
|
+
|
|
|
|
+ SQL_PARAM_INPUT int = 1
|
|
|
|
+ SQL_PARAM_OUTPUT int = 2
|
|
|
|
+ SQL_PARAM_INPUTOUTPUT int = 3
|
|
|
|
+ SQL_PARAM_RETURNVALUE int = 6
|
|
|
|
+
|
|
|
|
+ SQL_XG_C_CHAR int = 2
|
|
|
|
+ SQL_XG_C_CLOB int = 41
|
|
|
|
+ SQL_XG_C_BLOB int = 42
|
|
|
|
+ SQL_XG_C_NULL int = -11
|
|
|
|
+
|
|
|
|
+ BIND_PARAM_BY_NAME int = 62
|
|
|
|
+ BIND_PARAM_BY_POS int = 63
|
|
|
|
+)
|
|
|
|
+
|
|
type connector struct {
|
|
type connector struct {
|
|
dsn string
|
|
dsn string
|
|
}
|
|
}
|
|
|
|
|
|
-func NewConnector(dsn string) *connector {
|
|
|
|
- return &connector{dsn: dsn}
|
|
|
|
-}
|
|
|
|
|
|
+// func NewConnector(dsn string) *connector {
|
|
|
|
+// dsnL := strings.ToLower(dsn)
|
|
|
|
+// fmt.Println("dsnL: ", dsnL)
|
|
|
|
+// return &connector{dsn: dsnL}
|
|
|
|
+// }
|
|
|
|
|
|
var IPS_COUNTER int = 0
|
|
var IPS_COUNTER int = 0
|
|
|
|
|
|
@@ -32,11 +80,16 @@ func (self *connector) Connect(ctx context.Context) (driver.Conn, error) {
|
|
obj := &xugusqlConn{conn: nil}
|
|
obj := &xugusqlConn{conn: nil}
|
|
//connKeyValue := C.CString(self.dsn)
|
|
//connKeyValue := C.CString(self.dsn)
|
|
|
|
|
|
|
|
+ dsnConfig := parseDSN(self.dsn)
|
|
|
|
+ fmt.Println("self.dsn:", strings.ToLower(self.dsn))
|
|
|
|
+ obj.dsnConfig = dsnConfig
|
|
|
|
+ fmt.Println("connector: ", self.dsn)
|
|
|
|
+ fmt.Println("dsnConfig: ", dsnConfig)
|
|
defer func() {
|
|
defer func() {
|
|
// cgo_c_free(unsafe.Pointer(connKeyValue))
|
|
// cgo_c_free(unsafe.Pointer(connKeyValue))
|
|
}()
|
|
}()
|
|
- fmt.Println("Connect")
|
|
|
|
- re, _ := xgc_connect(ctx, self.dsn, &obj.conn)
|
|
|
|
|
|
+
|
|
|
|
+ re, _ := xg_connect(ctx, obj)
|
|
if re < 0 {
|
|
if re < 0 {
|
|
return nil, obj.get_error()
|
|
return nil, obj.get_error()
|
|
// pos := strings.Index(strings.ToUpper(self.dsn), "IPS=")
|
|
// pos := strings.Index(strings.ToUpper(self.dsn), "IPS=")
|
|
@@ -56,18 +109,22 @@ func (self *connector) Connect(ctx context.Context) (driver.Conn, error) {
|
|
return obj, nil
|
|
return obj, nil
|
|
}
|
|
}
|
|
|
|
|
|
-func xgc_connect(ctx context.Context, pdsn string, __pConn *net.Conn) (int, error) {
|
|
|
|
- fmt.Println("xgc_connect pdsn:", pdsn)
|
|
|
|
- return XGSOpenConn(ctx, pdsn, __pConn)
|
|
|
|
|
|
+func xg_connect(ctx context.Context, __pConn *xugusqlConn) (int, error) {
|
|
|
|
+
|
|
|
|
+ return xgSockOpenConn(ctx, __pConn)
|
|
}
|
|
}
|
|
-func xgc_connect_ips(ctx context.Context, pdsn *string, __pConn *net.Conn) int {
|
|
|
|
|
|
+
|
|
|
|
+// ips未实现
|
|
|
|
+func xg_connect_ips(ctx context.Context, __pConn *net.Conn) int {
|
|
return 0
|
|
return 0
|
|
}
|
|
}
|
|
|
|
|
|
-func XGSOpenConn(ctx context.Context, pdsn string, __pConn *net.Conn) (int, error) {
|
|
|
|
|
|
+func xgSockOpenConn(ctx context.Context, __pConn *xugusqlConn) (int, error) {
|
|
fmt.Println("XGSOpenConn")
|
|
fmt.Println("XGSOpenConn")
|
|
|
|
+
|
|
nd := net.Dialer{Timeout: 5 * time.Second}
|
|
nd := net.Dialer{Timeout: 5 * time.Second}
|
|
- netConn, err := nd.DialContext(ctx, "tcp", pdsn)
|
|
|
|
|
|
+
|
|
|
|
+ netConn, err := nd.DialContext(ctx, "tcp", fmt.Sprintf("%s:%s", __pConn.IP, __pConn.Port))
|
|
if err != nil {
|
|
if err != nil {
|
|
fmt.Println("tcp", err)
|
|
fmt.Println("tcp", err)
|
|
return -8, err
|
|
return -8, err
|
|
@@ -81,18 +138,19 @@ func XGSOpenConn(ctx context.Context, pdsn string, __pConn *net.Conn) (int, erro
|
|
}
|
|
}
|
|
|
|
|
|
//发送
|
|
//发送
|
|
|
|
+ //fmt.Printf("login database = '%s' user = '%s' password = '%s' version='201' ", __pConn.Database, __pConn.User, __pConn.Password)
|
|
|
|
|
|
- message := "login database = 'SYSTEM' user = 'SYSDBA' password = 'SYSDBA' version='201' "
|
|
|
|
-
|
|
|
|
- _, err = netConn.Write([]byte(message))
|
|
|
|
|
|
+ // message := "login database = 'SYSTEM' user = 'SYSDBA' password = 'SYSDBA' version='201' "
|
|
|
|
+ dsnMessage := generateLoginString(__pConn.dsnConfig)
|
|
|
|
+ _, err = netConn.Write([]byte(dsnMessage))
|
|
if err != nil {
|
|
if err != nil {
|
|
fmt.Println("发送数据失败:", err)
|
|
fmt.Println("发送数据失败:", err)
|
|
|
|
|
|
}
|
|
}
|
|
- fmt.Println("数据已发送:", message)
|
|
|
|
|
|
+ fmt.Println("数据已发送:", dsnMessage)
|
|
|
|
|
|
buffer := make([]byte, 1024)
|
|
buffer := make([]byte, 1024)
|
|
- n, err := netConn.Read(buffer)
|
|
|
|
|
|
+ n, err := __pConn.conn.Read(buffer)
|
|
if err != nil {
|
|
if err != nil {
|
|
fmt.Println("Error reading from server:", err)
|
|
fmt.Println("Error reading from server:", err)
|
|
|
|
|
|
@@ -101,7 +159,117 @@ func XGSOpenConn(ctx context.Context, pdsn string, __pConn *net.Conn) (int, erro
|
|
return 1, nil
|
|
return 1, nil
|
|
}
|
|
}
|
|
|
|
|
|
-func (self *xugusqlConn) get_error() error {
|
|
|
|
|
|
+func parseDSN(dsn string) dsnConfig {
|
|
|
|
+ // Initialize a dsnConfig struct
|
|
|
|
+ var config dsnConfig
|
|
|
|
+
|
|
|
|
+ // Split the string by semicolons
|
|
|
|
+ pairs := strings.Split(dsn, ";")
|
|
|
|
|
|
- return errors.New("errors")
|
|
|
|
|
|
+ // Iterate over the pairs and map them to the struct fields
|
|
|
|
+ for _, pair := range pairs {
|
|
|
|
+ // Split each pair by the equals sign
|
|
|
|
+ kv := strings.SplitN(pair, "=", 2)
|
|
|
|
+ if len(kv) != 2 {
|
|
|
|
+ continue
|
|
|
|
+ }
|
|
|
|
+ key, value := strings.TrimSpace(kv[0]), strings.Trim(strings.TrimSpace(kv[1]), "'")
|
|
|
|
+ keyL := strings.ToLower(key)
|
|
|
|
+
|
|
|
|
+ // Map the key to the appropriate struct field
|
|
|
|
+ switch keyL {
|
|
|
|
+ case "ip":
|
|
|
|
+ config.IP = value
|
|
|
|
+ case "port":
|
|
|
|
+ config.Port = value
|
|
|
|
+ case "db":
|
|
|
|
+ config.Database = value
|
|
|
|
+ case "user":
|
|
|
|
+ config.User = value
|
|
|
|
+ case "pwd":
|
|
|
|
+ config.Password = value
|
|
|
|
+ case "encryptor":
|
|
|
|
+ config.Encryptor = value
|
|
|
|
+ case "char_set":
|
|
|
|
+ config.CharSet = value
|
|
|
|
+ case "time_zone":
|
|
|
|
+ config.TimeZone = value
|
|
|
|
+ case "iso_level":
|
|
|
|
+ config.IsoLevel = value
|
|
|
|
+ case "lock_timeout":
|
|
|
|
+ config.LockTimeout = value
|
|
|
|
+ case "auto_commit":
|
|
|
|
+ config.AutoCommit = value
|
|
|
|
+ case "strict_commit":
|
|
|
|
+ config.StrictCommit = value
|
|
|
|
+ case "result":
|
|
|
|
+ config.Result = value
|
|
|
|
+ case "return_schema":
|
|
|
|
+ config.ReturnSchema = value
|
|
|
|
+ case "return_cursor_id":
|
|
|
|
+ config.ReturnCursorID = value
|
|
|
|
+ case "lob_ret":
|
|
|
|
+ config.LobRet = value
|
|
|
|
+ case "return_rowid":
|
|
|
|
+ config.ReturnRowid = value
|
|
|
|
+ case "version":
|
|
|
|
+ config.Version = value
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return config
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func generateLoginString(config dsnConfig) string {
|
|
|
|
+ baseString := "login database = '%s' user = '%s' password = '%s' "
|
|
|
|
+ additionalParams := ""
|
|
|
|
+
|
|
|
|
+ if config.Encryptor != "" {
|
|
|
|
+ additionalParams += fmt.Sprintf(" encryptor='%s'", config.Encryptor)
|
|
|
|
+ }
|
|
|
|
+ if config.CharSet != "" {
|
|
|
|
+ additionalParams += fmt.Sprintf(" char_set='%s'", config.CharSet)
|
|
|
|
+ }
|
|
|
|
+ if config.TimeZone != "" {
|
|
|
|
+ additionalParams += fmt.Sprintf(" time_zone='%s'", config.TimeZone)
|
|
|
|
+ }
|
|
|
|
+ if config.IsoLevel != "" {
|
|
|
|
+ additionalParams += fmt.Sprintf(" iso_level='%s'", config.IsoLevel)
|
|
|
|
+ }
|
|
|
|
+ if config.LockTimeout != "" {
|
|
|
|
+ additionalParams += fmt.Sprintf(" lock_timeout='%s'", config.LockTimeout)
|
|
|
|
+ }
|
|
|
|
+ if config.AutoCommit != "" {
|
|
|
|
+ additionalParams += fmt.Sprintf(" auto_commit='%s'", config.AutoCommit)
|
|
|
|
+ }
|
|
|
|
+ if config.StrictCommit != "" {
|
|
|
|
+ additionalParams += fmt.Sprintf(" strict_commit='%s'", config.StrictCommit)
|
|
|
|
+ }
|
|
|
|
+ if config.Result != "" {
|
|
|
|
+ additionalParams += fmt.Sprintf(" result='%s'", config.Result)
|
|
|
|
+ }
|
|
|
|
+ if config.ReturnSchema != "" {
|
|
|
|
+ additionalParams += fmt.Sprintf(" return_schema='%s'", config.ReturnSchema)
|
|
|
|
+ }
|
|
|
|
+ if config.ReturnCursorID != "" {
|
|
|
|
+ additionalParams += fmt.Sprintf(" return_cursor_id='%s'", config.ReturnCursorID)
|
|
|
|
+ }
|
|
|
|
+ if config.LobRet != "" {
|
|
|
|
+ additionalParams += fmt.Sprintf(" lob_ret='%s'", config.LobRet)
|
|
|
|
+ }
|
|
|
|
+ if config.ReturnRowid != "" {
|
|
|
|
+ additionalParams += fmt.Sprintf(" return_rowid='%s'", config.ReturnRowid)
|
|
|
|
+ }
|
|
|
|
+ if config.Version != "" {
|
|
|
|
+ additionalParams += fmt.Sprintf(" version='%s'", config.Version)
|
|
|
|
+ } else {
|
|
|
|
+ additionalParams += " version='201'"
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ finalString := fmt.Sprintf(baseString, config.Database, config.User, config.Password)
|
|
|
|
+ if additionalParams != "" {
|
|
|
|
+ finalString += additionalParams
|
|
|
|
+ }
|
|
|
|
+ //finalString += " version='201'"
|
|
|
|
+ return finalString
|
|
}
|
|
}
|