Convert decimal to string retrieve from SAP HANA db using go-hdb driver in golang

huangapple go评论145阅读模式
英文:

Convert decimal to string retrieve from SAP HANA db using go-hdb driver in golang

问题

我是新手学习 Golang(但对于 HANA 不陌生),我正在尝试使用 go-hdb 从 HANA DB SPS6 的 TCURR 表中提取数据。根据我了解,在该表中,UKURSFFACTTFACT 都是 HANA DB 中的 Decimal 类型。

然而,当我尝试使用 row.Scan 将数据提取为 Float64 时,出现了以下错误:

> 2016/08/18 10:18:31 sql: 在列索引 5 上进行扫描时出错:将 driver.Value 类型 []uint8 ("@\xe2\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0060") 转换为 float64 时出现无效语法

我尝试阅读和理解这个错误,看起来需要 uint8 数据类型(或字节),但是我不知道如何将这些 uint8/字节转换为字符串。

是否有人之前遇到过这个问题,以及如何正确获取十进制数据并将其显示(例如打印到控制台)?

英文:

I am new to Golang (but not on HANA), and I am trying to test out the go-hdb to pull out data from TCURR table (from HANA DB SPS6). From what I understand is in that table, UKURS, FFACT, and TFACT are all Decimals in HANA DB.
However when retrieving from Go, which I tried fetch using row.Scan to Float64 like this:

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)
}

But alas, getting error like this

> 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

I try to read and understand the error it looks like needs uint8 data type (or byte), however, I am stuck with how to convert those uint8/byte into string.

Is there anyone have this problem before and how to getting decimal data and displayed it properly (ie print them into console)?

答案1

得分: 1

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

After to look and understand the driver package a while, I found out there is a function that actually answered my question. The function is reside within decimal.go with function name decodeDecimal(). Due to it is used by internal only, I copy the source code and paste to my code.

The code is something like this:

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)

Function of 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
}

Function 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)
}

huangapple
  • 本文由 发表于 2016年8月22日 17:37:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/39076067.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定