go-sql-driver / mysql

Go MySQL Driver is a MySQL driver for Go's (golang) database/sql package
https://pkg.go.dev/github.com/go-sql-driver/mysql
Mozilla Public License 2.0
14.51k stars 2.31k forks source link

mysql error `ERROR 3141` is not cathed in db.query() #1622

Closed sora91s closed 2 months ago

sora91s commented 2 months ago

Issue description

mysql error ERROR 3141 is not cathed in query()

sql: select JSON_TYPE('[1,2,3'); '[1,2,3' is not a json str, so So an error will be reported for JSON_TYPE

image

but when i use query, no error is reported

image

Example code

func main() { db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", "user", "pswd", "127.0.0.1", 3306, "database")) if err != nil { panic(err) } sqlStr := "select JSON_TYPE('[1,2,3');" err = query(db, sqlStr) fmt.Printf("error: %v", err) }

func query(db *sql.DB, sqlStr string) error { _, err := db.Query(sqlStr) // ignore_security_alert if err != nil { fmt.Println(fmt.Sprintf("db query err: %s, sql:%s", err.Error(), sqlStr)) panic(err) } return nil }

Error log

no error log but it should be error

Configuration

Driver version (or git SHA):

Go version: run go version in your console

Go 1.21.3

Server version: E.g. MySQL 5.6, MariaDB 10.0.20

MySQL 8.0/5.7

Server OS: E.g. Debian 8.1 (Jessie), Windows 10

MacOs

methane commented 2 months ago

No error while sending query. You need to read result and check error.

sora91s commented 2 months ago

image

no result in rows, what should i do?

methane commented 2 months ago

You don't call rows.Err() nor rows.Close().

sora91s commented 2 months ago

image

can you try it?

select JSON_TYPE('[1,2,3');

sora91s commented 2 months ago

@methane Can you help me solve it?

nussjustin commented 2 months ago

Rows.Err must be used after calling Rows.Next and returns the error, if any, that occurred during scanning.

Calling it before calling Rows.Next will always return nil.

From the docs of Rows.Next

Next prepares the next result row for reading with the Rows.Scan method. It returns true on success, or false if there is no next result row or an error happened while preparing it. Rows.Err should be consulted to distinguish between the two cases

Example:

package main

import (
    "database/sql"
    "fmt"
    "log"

    _ "github.com/go-sql-driver/mysql"
)

func main() {
    log.SetFlags(0)

    db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", "root", "root", "127.0.0.1", 3306, "test"))
    if err != nil {
        log.Fatalf("error in sql.Open: %s", err)
    }
    defer db.Close()

    rows, err := db.Query(`SELECT JSON_TYPE('[1,2,3')`)
    if err != nil {
        log.Fatalf("error in db.Query: %s", err)
    }
    defer rows.Close()

    for rows.Next() {
        log.Println("scanned row")

        var dest any

        if err := rows.Scan(&dest); err != nil {
            log.Fatalf("error in rows.Scan: %s", err)
        }
    }

    if err := rows.Err(); err != nil {
        log.Fatalf("error in rows.Err: %s", err)
    }
}

Output:

error in rows.Err: Error 3141 (22032): Invalid JSON text in argument 1 to function json_type: "Missing a comma or ']' after an array element." at position 6.

You cal also use DB.QueryRow if you know the query only returns one row, in which case Row.Scan will return the error:

    // ...

    row := db.QueryRow(`SELECT JSON_TYPE('[1,2,3')`)

    var dest any

    if err := row.Scan(&dest); err != nil {
        log.Fatalf("error in rows.Scan: %s", err)
    }
}
sora91s commented 2 months ago

thanks