Does a Go Mysql driver exist that supports multiple statements within a single string?

前端 未结 5 2110
生来不讨喜
生来不讨喜 2020-12-18 04:44

I\'m trying to find a MySql driver that i can use with Go which supports issuing multiple SQL statements in one call. For example i might wish to create a database using the

相关标签:
5条回答
  • 2020-12-18 05:01

    the github.com/go-sql-driver/mysql can be configured to accept multiple statements with the multiStatements=true connection parameter.

    The documentation clearly states why you should be careful doing it. See https://github.com/go-sql-driver/mysql

    0 讨论(0)
  • 2020-12-18 05:06

    I would recommend simply making 2 calls. Why not? It makes the code easier to grok and improves the error handling.

    The other option, if you have a large SQL file from the dump is to shell out and execute the whole thing in one go.

    0 讨论(0)
  • 2020-12-18 05:16

    Adding an example for the answer from @ithkuil regarding multiStatements for the go-sql-driver package for reference. (I didn't have enough rep to add as a comment).

    The parameter for multiStatements is added onto the dataSourceName string for your sql.Open call. e.g.

    db, err := sql.Open("mysql", "user:pass@tcp(localhost:3306)/dbname?multiStatements=true")
    

    It's recommended that you not use such a db handler for processing user input, but it works great for processing known sql files.

    0 讨论(0)
  • 2020-12-18 05:17

    https://github.com/ziutek/mymysql

    Can do it. Although you have to use its interface vs the go defined one. The go official interface doesn't handle it, or multiple return values.

    package main
    
    import (
        "flag"
        "fmt"
    
        "github.com/ziutek/mymysql/autorc"
        "github.com/ziutek/mymysql/mysql"
        _ "github.com/ziutek/mymysql/thrsafe"
    )
    
    type ScanFun func(int, []mysql.Row, mysql.Result) error
    
    func RunSQL(hostport, user, pass, db, cmd string, scan ScanFun) error {
        conn := autorc.New("tcp", "", hostport, user, pass, db)
    
        err := conn.Reconnect()
        if err != nil {
            return err
        }
    
        res, err := conn.Raw.Start(cmd)
        if err != nil {
            return err
        }
    
        rows, err := res.GetRows()
        if err != nil {
            return err
        }
    
        RScount := 0
        scanErr := error(nil)
    
        for {
            if scanErr == nil {
                func() {
                    defer func() {
                        if x := recover(); x != nil {
                            scanErr = fmt.Errorf("%v", x)
                        }
                    }()
                    scanErr = scan(RScount, rows, res)
                }()
            }
    
            if res.MoreResults() {
                res, err = res.NextResult()
                if err != nil {
                    return err
                }
                rows, err = res.GetRows()
                if err != nil {
                    return err
                }
            } else {
                break
            }
    
            RScount++
        }
        return scanErr
    }
    
    func main() {
        host := flag.String("host", "localhost:3306", "define the host where the db is")
        user := flag.String("user", "root", "define the user to connect as")
        pass := flag.String("pass", "", "define the pass to use")
        db := flag.String("db", "information_schema", "what db to default to")
    
        sql := flag.String("sql", "select count(*) from columns; select * from columns limit 1;", "Query to run")
    
        flag.Parse()
    
        scan := func(rcount int, rows []mysql.Row, res mysql.Result) error {
            if res.StatusOnly() {
                return nil
            }
    
            for idx, row := range rows {
                fmt.Print(rcount, "-", idx, ") ")
                for i, _ := range row {
                    fmt.Print(row.Str(i))
                    fmt.Print(" ")
                }
                fmt.Println("")
            }
            return nil
        }
    
        fmt.Println("Host - ", *host)
        fmt.Println("Db   - ", *db)
        fmt.Println("User - ", *user)
    
        if err := RunSQL(*host, *user, *pass, *db, *sql, scan); err != nil {
            fmt.Println(err)
        }
    }
    
    0 讨论(0)
  • 2020-12-18 05:28

    Bluntly put, do not issue multiple statements in a single call. It is a security issue. If a hacker can get in a little bit, he can take over your machine. (Read about "SQL Injection".)

    Stored Routines give you a safe way to combine statements (with some restrictions).

    0 讨论(0)
提交回复
热议问题