Skip to content

Bad extra byte (0x00) at the beginning of TIME values. #139

@xiam

Description

@xiam

I started with a structure like this:

DROP TABLE IF EXISTS `data_types`;

CREATE TABLE `data_types` (
  `_time` time NOT NULL,
  PRIMARY KEY (`id`)
);

Then I inserted a time value:

INSERT INTO `data_types` VALUES ('12:34:56');

In the client side (with Go), I used a string with a "?" condition to make a SELECT query, like this:

rows, err := db.Query(`SELECT _time FROM data_types WHERE id = ?`, 1)

Result was that every time I used a condition with "?", an extra 0x00 character was added to the beginning of the result column, making it 9 bytes long ("\x0012:23:56") instead of 8 bytes ("12:34:56") making the result different from the original time.

$ go run main.go
_time :  [0 48 49 58 48 50 58 48 51]
-----------------------------------

I tracked the error down to packets.go, the 0 at the beginning is just the value of the sign byte when data[pos] is not 1.

1017       var sign byte
1018       if data[pos] == 1 {
1019         sign = byte('-')
1020       }
1021 
1022       switch num {
1023       case 8:
1024         dest[i] = []byte(fmt.Sprintf(
1025           "%c%02d:%02d:%02d",
1026           sign,

Strangely enough, this bug does not appear if a don't use a condition with "?".

Full test code follows:

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/go-sql-driver/mysql"
)

func main() {

    db, err := sql.Open("mysql", "test:test@unix(/var/run/mysqld/mysqld.sock)/tests")

    if err != nil {
        fmt.Println(err)
        return
    }

    defer db.Close()

    /*
        Problem arises when we use conditions with '?' arguments.
    */
    rows, err := db.Query(`SELECT _time FROM data_types WHERE id = ?`, 1)

    /*
        These conditions seem to work just fine.
    */
    //rows, err := db.Query(`SELECT _time FROM data_types WHERE 1 = 1`)
    //rows, err := db.Query(`SELECT _time FROM data_types`)

    if err != nil {
        fmt.Printf("%q: %s\n", err)
        return
    }

    columns, err := rows.Columns()
    if err != nil {
        fmt.Printf("%q: %s\n", err)
        return
    }

    values := make([]*sql.RawBytes, len(columns))

    scanArgs := make([]interface{}, len(values))
    for i := range values {
        scanArgs[i] = &values[i]
    }

    /*
        Expected output:

        _time :  [48 49 58 48 50 58 48 51]
        -----------------------------------
    */
    for rows.Next() {
        err = rows.Scan(scanArgs...)

        if err != nil {
            panic(err.Error())
        }

        for i, col := range values {
            if col != nil {
                fmt.Println(columns[i], ": ", *col)
            }
        }
        fmt.Println("-----------------------------------")
    }

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions