2016-08-22 4 views
1

Я новичок в Golang (но не в HANA), и я пытаюсь проверить go-hdb, чтобы вытащить данные из TCURR таблицу (из HANA DB SPS6). Из того, что я понимаю, находится в этой таблице, UKURS, FFACT, и TFACT все десятичные числа в базе данных HANA. Однако при получении от Go, которую я попытался извлечь с помощью row.Scan к Float64 так:Преобразование десятичной строки в строку из SAP HANA db с использованием драйвера go-hdb в golang

var mandt, kurst, fcurr, tcurr, gdatu, datum string 
var ukurs float64 
var ffact, tfact float64 

if err := rows.Scan(&mandt, &kurst, &fcurr, &tcurr, &gdatu, &ukurs, &ffact, &tfact, &datum); err != nil { 
    log.Fatal(err) 
} 

Но увы, получаю ошибку, как этот

2016/08/18 10:18:31 sql: Scan error on column index 5: converting driver.Value type []uint8 ("@\xe2\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0060") to a float64: invalid syntax 

Я стараюсь читать и понимать ошибку он выглядит как тип данных uint8 (или байт), однако я застрял в том, как преобразовать эти uint8/byte в строку.

Есть ли у кого-нибудь проблемы до и как получить десятичные данные и правильно их отобразить (т.е. распечатать их в консоли)?

+0

Похоже вы передаете аргументы в неправильном порядке в 'строк .Scan() ', возможно, в индексе' 5' (на основе нуля) должно быть 'datum', а не' ukurs'? – icza

+0

извините, но из индекса 0 - мант, курст, fcurr, tcurr, gdatu, а затем ukurs - индекс 5 (основанный на нуле) –

ответ

0

После того, как посмотреть и понять пакет драйверов, я обнаружил, что есть функция, которая фактически ответила на мой вопрос. Функция находится в пределах decimal.go с именем функции decodeDecimal(). Из-за того, что он используется только внутри, я копирую исходный код и вставляю его в свой код.

Код что-то вроде этого:

var mandt, kurst, fcurr, tcurr, gdatu, datum string 
var ukurs, ffact, tfact []byte 
if err := rows.Scan(&mandt, &kurst, &fcurr, &tcurr, &gdatu, &ukurs, &ffact, &tfact, &datum); err != nil { 
    WriteMsg("SCAN") 
    log.Fatal(err) 
} 

var bi big.Int 
var z float64 
var neg bool 
var i int 

var record []string 

record = append(record, mandt) 
record = append(record, kurst) 
record = append(record, fcurr) 
record = append(record, tcurr) 
record = append(record, gdatu) 

// ukurs 
neg, i = decodeDecimal(ukurs, &bi) 
z = BigIntToFloat(neg, &bi, i) 
record = append(record, fmt.Sprintf("%.4f", z)) 

// ffact 
neg, i = decodeDecimal(ffact, &bi) 
z = BigIntToFloat(neg, &bi, i) 
record = append(record, fmt.Sprintf("%.4f", z)) 

// tfact 
neg, i = decodeDecimal(tfact, &bi) 
z = BigIntToFloat(neg, &bi, i) 
record = append(record, fmt.Sprintf("%.4f", z)) 

record = append(record, datum) 

Функция decodeDecimal()

func decodeDecimal(b []byte, m *big.Int) (bool, int) { 

    //bigint word size (*--> src/pkg/math/big/arith.go) 
     const (
     dec128Bias = 6176 
     // Compute the size _S of a Word in bytes. 
     _m = ^big.Word(0) 
     _logS = _m>>8&1 + _m>>16&1 + _m>>32&1 
     _S = 1 << _logS 
    ) 

    neg := (b[15] & 0x80) != 0 
    exp := int((((uint16(b[15])<<8)|uint16(b[14]))<<1)>>2) - dec128Bias 

    b14 := b[14] // save b[14] 
    b[14] &= 0x01 // keep the mantissa bit (rest: sign and exp) 

    //most significand byte 
    msb := 14 
    for msb > 0 { 
     if b[msb] != 0 { 
      break 
     } 
     msb-- 
    } 

    //calc number of words 
    numWords := (msb/_S) + 1 
    w := make([]big.Word, numWords) 

    k := numWords - 1 
    d := big.Word(0) 
    for i := msb; i >= 0; i-- { 
     d |= big.Word(b[i]) 
     if k*_S == i { 
      w[k] = d 
      k-- 
      d = 0 
     } 
     d <<= 8 
    } 
    b[14] = b14 // restore b[14] 
    m.SetBits(w) 
    return neg, exp 
} 

Функция BigIntToFloat()

func BigIntToFloat(sign bool, m *big.Int, exp int) float64 { 
    var neg int64 
    if sign { 
     neg = -1 
    } else { 
     neg = 1 
    } 

    return float64(neg*m.Int64()) * math.Pow10(exp) 
}