douluokuang7184
douluokuang7184
2019-03-04 17:44

Redshift返回[] uint8而不是整数,在它们之间进行转换将返回不正确的值

已采纳

I have a service which takes a SQL Query, runs the query on Amazon Redshift, using the database/sql drivers. However, I can't convert the result to a struct, because the queries are big data tasks on various tables, not created within this service. So I have to return a 'loose' data structure. I'm parsing the data returned into JSON and storing it in S3.

However, I'm having some odd issues with the data types returned. The queries, for numeric columns, return a map of uint8's instead of a numeric value. I understand that this is because the database driver can't have an opinion on what to convert it to because it could be imprecise. But I can't seem to be able to convert between []uint8 and an integer either.

Here's my code that queries the database:

// Execute executes SQL commands
func (r *Runner) Execute(query string, args ...interface{}) (types.Results, error) {
    var results types.Results
    rows, err := r.db.Query(query, args...)
    if err != nil {
        return results, err
    }

    columns, _ := rows.Columns()
    colNum := len(columns)

    values := make([]interface{}, colNum)
    for i := range values {
        var ii interface{}
        values[i] = &ii
    }

    for rows.Next() {
        rows.Scan(values...)
        result := make(types.Result)
        for i, colName := range columns {
            rawValue := *(values[i].(*interface{}))
            if reflect.TypeOf(rawValue).String() == "[]uint8" {
                byteVal := rawValue.([]byte)
                val := Intfrombytes(byteVal)
                log.Println("Converted:", val)
            }
            result[colName] = rawValue
        }
        results = append(results, result)
    }
    return results, nil
}

I created the following function to attempt to convert between []uint8 and uint32.

func Intfrombytes(bytes []uint8) uint16 {
    bits := binary.LittleEndian.Uint16(bytes)
    return bits
}

However, if I insert 200 into that table, I get back 12339. The approach feels pretty flaky, generally. I'm doubting my decision to use Go for this as I'm dealing with undefined, loose data structures.

Is there a better approach to generic queries such as my example, or is there a way I can convert my numeric results into an integer?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

1条回答

  • duankezong4064 duankezong4064 2年前

    I think you might be interpreting a string ([]uint8 == []byte), actually. See https://play.golang.org/p/Rfpey2NPiI7

    originalValue := []uint8{0x32, 0x30, 0x30} // "200"
    bValue := []byte(originalValue) // byte is a uint8 anyway
    fmt.Printf("Converted to uint16: %d
    ", binary.LittleEndian.Uint16(bValue))
    fmt.Printf("Actual value: %s", string(bValue))
    

    This has bitten me before when dealing with pq and some crypto code.

    点赞 评论 复制链接分享

相关推荐