使用golang中的go-hdb驱动程序将十进制转换为从SAP HANA数据库检索的字符串

2mbi3lxu  于 2023-02-27  发布在  Go
关注(0)|答案(1)|浏览(158)

我是Golang的新手(但不是HANA),我正在尝试测试go-hdb从TCURR表(来自HANA DB SPS6)中提取数据。根据我对该表的理解,* UKURS FFACT * 和 * TFACT * 在HANA DB中都是小数。但是,当从Go中检索时,我尝试使用row提取。扫描到Float64,如下所示:

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年8月18日10:18:31 SQL:列索引5上的扫描错误:正在将驱动程序.值类型[] uint8("@\xe2\x01\x00\x00\x00\x00\x00\x00\x00\x00\x0060 ")转换为浮点型64:无效语法
我试着阅读和理解它看起来需要uint8数据类型(或字节)的错误,然而,我被如何将那些uint8/字节转换为字符串所困。
有没有人有这个问题之前,以及如何获得十进制数据和显示它正确(即打印到控制台)?

eufgjt7s

eufgjt7s1#

在看了一段时间并理解了驱动程序包后,我发现有一个函数确实回答了我的问题。该函数位于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)
}

相关问题