1

I'm new in go, and trying just read data from MySQL. Schema: "id: INT(11), head: TEXT, filter: BIT(64)"

I tried to do this in common way:

type News struct {
    Id      int    `field:"id"`
    Head    string `field:"head"`
    Filter  uint64 `field:"filter"`
}
...
rows.Scan(&item.Id, &item.Head, &item.Filter)

and got:

Scan error on column index 2, name "filter": converting NULL to uint64 is unsupported

I tried some example with reflection, but without result.

I tried make own type like here (really don't understand this):

type BitMask uint64
func (bits *BitMask) Scan(src interface{}) error {
    str, ok := src.(string)
    if !ok {
        return fmt.Errorf("Unexpected type for BitMask: %T\n", src)
    }
    fmt.Println(str)
    //var v uint64 = 0
    //*bits = v // <- Also have error here
    return nil
}

And got similar error: "Unexpected type for BitMask: < nil>"

LynXz
  • 78
  • 8
  • Any reason to prefer `BIT` to `UNSIGNED BIGINT`? – tadman Sep 17 '20 at 23:59
  • Not sure, not expert in SQL too. Seems like MySQL can make same bit operations with UNSIGNED BIGINT too. If there no any pros except representation, I can change it to int. But BIT exist for some reason, don't want to make mistake for future. And raw queries to SQL will look more understandable for our analytics. – LynXz Sep 18 '20 at 00:22
  • 1
    Possibly, but another guess is that field has to be `NOT NULL`. – tadman Sep 18 '20 at 00:30
  • Thanks, @tadman, this was a reason. I add `if src == nil {return nil}; str, ok: = src. ([] byte) `in the begin of Scan function and it is work. Remains only to convert the byte array to a number. – LynXz Sep 18 '20 at 00:45
  • 1
    @LynXz maybe you want to use this https://golang.org/pkg/database/sql/#NullInt64 – Shubham Srivastava Sep 18 '20 at 03:53
  • @ShubhamSrivastava looks like exactly what I need as base class for `type BitMask sql.NullInt64`. But Scan `BIT` to `sql.NullInt64` not work: `converting driver.Value type []uint8 ("\x00\x00\x00\x00\x00\x00\x00\x00") to a int64: invalid syntax` – LynXz Sep 18 '20 at 09:39
  • @LynXz you can implement similar custom scanner for Bit Type; Just need to implement 2 fucntions – Shubham Srivastava Sep 18 '20 at 09:41

1 Answers1

0

I make this answer just to close question and summarize result. So there are 2 ways:

1 Write own type:

type BitMask sql.NullInt64

func (bits *BitMask) Scan(src interface{}) error {
  if src == nil {
    bits.Int64 = 0
    bits.Valid = false
    return nil
  }
  buf, ok := src.([]byte)
  if !ok {
    return fmt.Errorf("Unexpected type for BitMask: %T\n", src)
  }
  if len(buf) != 8 {
    bits.Int64 = 0
    bits.Valid = false
    return errors.New("Size of bit filed is not 8 bytes\n")
  }
  bits.Int64 = 0
  for i := range buf {
    bits.Int64 *= 256
    bits.Int64 = int64(buf[i])
  }
  bits.Valid = true
  return nil
}
  1. Don't use BIT(64), but UNSIGNED BIGINT instead. Because there are no advanteges, only problems. (That is what I'm going to do)
LynXz
  • 78
  • 8