Browse Source

first commit

GTong 11 months ago
commit
587f446ac2
7 changed files with 295 additions and 0 deletions
  1. 7 0
      go.mod
  2. 4 0
      go.sum
  3. 57 0
      main.go
  4. 48 0
      xugu/driver.go
  5. 107 0
      xugu/xugusql_connector.go
  6. 39 0
      xugu/xugusql_pconn.go
  7. 33 0
      xugu/xugusql_tranx.go

+ 7 - 0
go.mod

@@ -0,0 +1,7 @@
+module xg_driver
+
+go 1.22.2
+
+require github.com/go-sql-driver/mysql v1.8.1
+
+require filippo.io/edwards25519 v1.1.0 // indirect

+ 4 - 0
go.sum

@@ -0,0 +1,4 @@
+filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
+filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
+github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
+github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=

+ 57 - 0
main.go

@@ -0,0 +1,57 @@
+package main
+
+import (
+	"database/sql"
+	"fmt"
+	"log"
+	"net"
+	"os"
+
+	_ "xg_driver/xugu"
+)
+
+func main() {
+	// ctx := context.Background()
+	// conn := xugu.NewConnector("127.0.0.1:5138")
+	// conn.Connect(ctx)
+	db, err := sql.Open("xugusql", "127.0.0.1:5138")
+	_, err = db.Exec("create table go_test(c1 int, c2 varchar);")
+	if err != nil {
+		log.Fatal(err)
+	}
+	db.Close()
+}
+
+func testSend() {
+	db, err := sql.Open("mysql", "root:1234567@tcp(127.0.0.1:3306)/hello")
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer db.Close()
+
+	conn, err := net.Dial("tcp", "10.28.20.101:5190")
+	if err != nil {
+		fmt.Println("Error connecting:", err)
+		os.Exit(1)
+	}
+	defer conn.Close()
+
+	// 发送消息到服务器
+	message := "login   database = 'SYSTEM' user = 'SYSDBA'  password = 'SYSDBA' version='201' "
+	_, err = conn.Write([]byte(message))
+	if err != nil {
+		fmt.Println("Error writing to server:", err)
+		return
+	}
+
+	fmt.Println("Message sent:", message)
+
+	// 接收服务器的返回消息
+	buffer := make([]byte, 1024)
+	n, err := conn.Read(buffer)
+	if err != nil {
+		fmt.Println("Error reading from server:", err)
+		return
+	}
+	fmt.Println("Message from server:", string(buffer[:n]))
+}

+ 48 - 0
xugu/driver.go

@@ -0,0 +1,48 @@
+package xugu
+
+import (
+	"context"
+	"database/sql"
+	"database/sql/driver"
+	"time"
+)
+
+// XuguDriver is exported to make the driver directly accessible
+type XuguDriver struct{}
+
+/* Register Driver */
+func init() {
+
+	/* Register makes a database driver available by the provided name.
+	 * If Register is called twice with the same name or if driver is nil,
+	 * it panics.
+	 */
+	sql.Register("xugusql", &XuguDriver{})
+	timezone, _ := time.LoadLocation("Asia/Shanghai")
+	time.Local = timezone
+}
+
+// Open opens a database specified by its database driver name and a
+// driver-specific data source name, usually consisting of at least a
+// database name and connection information.
+//
+// Most users will open a database via a driver-specific connection
+// helper function that returns a *DB. No database drivers are included
+// in the Go standard library. See https://golang.org/s/sqldrivers for
+// a list of third-party drivers.
+//
+// Open may just validate its arguments without creating a connection
+// to the database. To verify that the data source name is valid, call
+// Ping.
+// The returned DB is safe for concurrent use by multiple goroutines
+// and maintains its own pool of idle connections. Thus, the Open
+// function should be called just once. It is rarely necessary to
+// close a DB.
+func (db XuguDriver) Open(dsn string) (driver.Conn, error) {
+	conn := &connector{dsn: dsn}
+	return conn.Connect(context.Background())
+}
+
+func (db XuguDriver) OpenConnector(dsn string) (driver.Connector, error) {
+	return &connector{dsn: dsn}, nil
+}

+ 107 - 0
xugu/xugusql_connector.go

@@ -0,0 +1,107 @@
+package xugu
+
+import (
+	"context"
+	"database/sql/driver"
+	"errors"
+	"fmt"
+	"net"
+	"time"
+)
+
+type connector struct {
+	dsn string
+}
+
+func NewConnector(dsn string) *connector {
+	return &connector{dsn: dsn}
+}
+
+var IPS_COUNTER int = 0
+
+// Driver implements driver.Connector interface.
+// Driver returns &XuguDriver{}
+func (self *connector) Driver() driver.Driver {
+	return &XuguDriver{}
+}
+
+// Connect implements driver.Connector interface.
+// Connect returns a connection to the database.
+func (self *connector) Connect(ctx context.Context) (driver.Conn, error) {
+
+	obj := &xugusqlConn{conn: nil}
+	//connKeyValue := C.CString(self.dsn)
+
+	defer func() {
+		//	cgo_c_free(unsafe.Pointer(connKeyValue))
+	}()
+	fmt.Println("Connect")
+	re, _ := xgc_connect(ctx, self.dsn, &obj.conn)
+	if re < 0 {
+		return nil, obj.get_error()
+		// pos := strings.Index(strings.ToUpper(self.dsn), "IPS=")
+		// if pos != -1 {
+		// 	IPS_COUNTER++
+		// 	re := xgc_connect_ips(ctx, &self.dsn, &obj.conn)
+		// 	if re < 0 {
+		// 		return nil, obj.get_error()
+		// 	}
+		// } else {
+		// 	re, _ := xgc_connect(ctx, self.dsn, &obj.conn)
+		// 	if re < 0 {
+		// 		return nil, obj.get_error()
+		// 	}
+	}
+
+	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 xgc_connect_ips(ctx context.Context, pdsn *string, __pConn *net.Conn) int {
+	return 0
+}
+
+func XGSOpenConn(ctx context.Context, pdsn string, __pConn *net.Conn) (int, error) {
+	fmt.Println("XGSOpenConn")
+	nd := net.Dialer{Timeout: 5 * time.Second}
+	netConn, err := nd.DialContext(ctx, "tcp", pdsn)
+	if err != nil {
+		fmt.Println("tcp", err)
+		return -8, err
+	}
+
+	// 启用 TCP 保活
+	if tc, ok := netConn.(*net.TCPConn); ok {
+		if err := tc.SetKeepAlive(true); err != nil {
+			//c.cfg.Logger.Print(err) // 如果设置保活失败,记录错误但不终止
+		}
+	}
+
+	//发送
+
+	message := "login   database = 'SYSTEM' user = 'SYSDBA'  password = 'SYSDBA' version='201' "
+
+	_, err = netConn.Write([]byte(message))
+	if err != nil {
+		fmt.Println("发送数据失败:", err)
+
+	}
+	fmt.Println("数据已发送:", message)
+
+	buffer := make([]byte, 1024)
+	n, err := netConn.Read(buffer)
+	if err != nil {
+		fmt.Println("Error reading from server:", err)
+
+	}
+	fmt.Println("Message from server:", string(buffer[:n]))
+	return 1, nil
+}
+
+func (self *xugusqlConn) get_error() error {
+
+	return errors.New("errors")
+}

+ 39 - 0
xugu/xugusql_pconn.go

@@ -0,0 +1,39 @@
+package xugu
+
+import (
+	"database/sql/driver"
+	"fmt"
+	"net"
+)
+
+type xugusqlConn struct {
+	conn net.Conn
+	/* xugusqlResult */
+	affectedRows int
+	insertId     int
+}
+
+func (self *xugusqlConn) Begin() (driver.Tx, error) {
+
+	err := self.exec("set auto_commit off;")
+	if err != nil {
+		return nil, self.get_error()
+	}
+
+	return &xugusqlTx{tconn: self}, nil
+}
+
+func (self *xugusqlConn) exec(query string) error {
+
+	return nil
+}
+
+func (self *xugusqlConn) Prepare(query string) (driver.Stmt, error) {
+
+	return nil, nil
+}
+
+func (self *xugusqlConn) Close() error {
+	fmt.Println("Close connection")
+	return nil
+}

+ 33 - 0
xugu/xugusql_tranx.go

@@ -0,0 +1,33 @@
+package xugu
+
+import "errors"
+
+type xugusqlTx struct {
+	tconn *xugusqlConn
+}
+
+func (self *xugusqlTx) Commit() error {
+	if self.tconn == nil {
+		return errors.New("Invalid connection")
+	}
+	err := self.tconn.exec("commit;")
+	if err != nil {
+		return err
+	}
+
+	return self.tconn.exec("set auto_commit on;")
+}
+
+func (self *xugusqlTx) Rollback() error {
+
+	if self.tconn == nil {
+		return errors.New("Invalid connection")
+	}
+	err := self.tconn.exec("rollback;")
+	if err != nil {
+		return err
+	}
+
+	return self.tconn.exec("set auto_commit on;")
+
+}