Gorm: Processing uuid in MSSQL procedure result rowset

Created on 11 Oct 2017  路  2Comments  路  Source: go-gorm/gorm

I have an MSSQL procedure that returns some kind of data, where the first row is uuid. Example below:
2017-10-11 19 44 46

According to manual I have defined structure and pass it into rows.Scan. Here is the sample code:

The base structure

package models

import (
    "fmt"
    "database/sql"

    "clients"
    "db"
)

type Base struct {
    rows *sql.Rows
}

func (base *Base) ExecuteQuery(sql string, values ...interface{}) (err error) {
    base.rows, err = db.Connection.Raw(sql, values...).Rows()
    if err != nil {
        return err
    }
    return nil
}

And the Company model

package models

import (
    "time"

    "github.com/satori/go.uuid"
)

type Companies struct {
    Base                `json:"-"`
    Items []interface{} `json:"readers"`
}

type CompanyItem struct {
    GUID           uuid.UUID `json:"guid"`
    Name           []byte    `json:"name"`
    Inn            []byte    `json:"inn"`
    Kpp            []byte    `json:"kpp"`
    IsOrganization int       `json:"is_organization"`
    LastName       []byte    `json:"last_name"`
    FirstName      []byte    `json:"first_name"`
    UpdatedAt      time.Time `json:"-"`
}

func SyncCompanies(since time.Time) (bool, error) {
    companies := &Companies{}
    err := companies.ExecuteQuery("exec pr_Site_Upload_Company @DateB = ?, @DateE = ?", since, time.Now())
    defer companies.rows.Close()
    if err != nil {
        return false, err
    }
    err = companies.processRows()
    if err != nil {
        return false, err
    }
        // Here goes some code
    return true, nil
}

func (companies *Companies) processRows() error {
    for companies.rows.Next() {
        item := &CompanyItem{}
        err := companies.rows.Scan(&item.GUID, &item.Name, &item.Inn, &item.Kpp, &item.IsOrganization,
            &item.LastName, &item.FirstName, &item.UpdatedAt)
        if err != nil {
            return err
        }
        companies.Items = append(companies.Items, item)
    }
    return nil
}

Everything is ok except GUID field. item.GUID does not match row's GUID. But strange - every time I execute query it returns same GUID if row didn't change, like there is some kind of algorithm which transforms row's guid into the new one
So the question is how to fix that? I couldn't find solution :(

Most helpful comment

I have found the solution, may be you will realise this in your project. The reason of this issue was that MsSQL stores uuid in specific format, so we need to read bytes in a non-standard order.
So the simple version of my solution looks like this:

  1. Read 'uuid' datatype field as []byte
  2. Here is the function which convers byte array into valid string representation of uuid:
func FormatUUID(uuid []byte) (string) {
    x1 := binary.LittleEndian.Uint32(uuid[0:])
    x2 := binary.LittleEndian.Uint16(uuid[4:])
    x3 := binary.LittleEndian.Uint16(uuid[6:])
    x4 := binary.BigEndian.Uint16(uuid[8:])
    x5 := binary.BigEndian.Uint16(uuid[10:])
    x6 := binary.BigEndian.Uint32(uuid[12:])
    return fmt.Sprintf("%08x-%04x-%04x-%04x-%04x%08x", x1, x2, x3, x4, x5, x6)
}

All 2 comments

I have found the solution, may be you will realise this in your project. The reason of this issue was that MsSQL stores uuid in specific format, so we need to read bytes in a non-standard order.
So the simple version of my solution looks like this:

  1. Read 'uuid' datatype field as []byte
  2. Here is the function which convers byte array into valid string representation of uuid:
func FormatUUID(uuid []byte) (string) {
    x1 := binary.LittleEndian.Uint32(uuid[0:])
    x2 := binary.LittleEndian.Uint16(uuid[4:])
    x3 := binary.LittleEndian.Uint16(uuid[6:])
    x4 := binary.BigEndian.Uint16(uuid[8:])
    x5 := binary.BigEndian.Uint16(uuid[10:])
    x6 := binary.BigEndian.Uint32(uuid[12:])
    return fmt.Sprintf("%08x-%04x-%04x-%04x-%04x%08x", x1, x2, x3, x4, x5, x6)
}

Thanks for the workaround. @RomanZagudaev It worked perfectly.

Is there a proper approach to read uniqueidentifier been implemented into the package github.com/jinzhu/gorm/dialects/mssql? //cc: @jinzhu Thanks

Was this page helpful?
0 / 5 - 0 ratings