o.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /*
  2. * Copyright (c) 2000-2018, 达梦数据库有限公司.
  3. * All rights reserved.
  4. */
  5. package dm
  6. import (
  7. "database/sql/driver"
  8. "math/big"
  9. "reflect"
  10. "strconv"
  11. "strings"
  12. )
  13. const (
  14. XDEC_MAX_PREC int = 38
  15. XDEC_SIZE = 21
  16. FLAG_ZERO int = 0x80
  17. FLAG_POSITIVE int = 0xC1
  18. FLAG_NEGTIVE int = 0x3E
  19. EXP_MAX int = 0xFF - 1 - FLAG_POSITIVE
  20. EXP_MIN int = FLAG_NEGTIVE + 1 - 0x7F
  21. NUM_POSITIVE int = 1
  22. NUM_NEGTIVE int = 101
  23. )
  24. type DmDecimal struct {
  25. sign int
  26. weight int
  27. prec int
  28. scale int
  29. digits string
  30. Valid bool
  31. }
  32. func NewDecimalFromInt64(x int64) (*DmDecimal, error) {
  33. return NewDecimalFromBigInt(big.NewInt(x))
  34. }
  35. func (d DmDecimal) ToInt64() int64 {
  36. return d.ToBigInt().Int64()
  37. }
  38. func NewDecimalFromFloat64(x float64) (*DmDecimal, error) {
  39. return NewDecimalFromBigFloat(big.NewFloat(x))
  40. }
  41. func (d DmDecimal) ToFloat64() float64 {
  42. f, _ := d.ToBigFloat().Float64()
  43. return f
  44. }
  45. func NewDecimalFromBigInt(bigInt *big.Int) (*DmDecimal, error) {
  46. return newDecimal(bigInt, len(bigInt.String()), 0)
  47. }
  48. func (d DmDecimal) ToBigInt() *big.Int {
  49. if d.isZero() {
  50. return big.NewInt(0)
  51. }
  52. var digits = d.digits
  53. if d.sign < 0 {
  54. digits = "-" + digits
  55. }
  56. i1, ok := new(big.Int).SetString(digits, 10)
  57. if !ok {
  58. return nil
  59. }
  60. if d.weight > 0 {
  61. i2, ok := new(big.Int).SetString("1"+strings.Repeat("0", d.weight), 10)
  62. if !ok {
  63. return nil
  64. }
  65. i1.Mul(i1, i2)
  66. } else if d.weight < 0 {
  67. i2, ok := new(big.Int).SetString("1"+strings.Repeat("0", -d.weight), 10)
  68. if !ok {
  69. return nil
  70. }
  71. i1.Quo(i1, i2)
  72. }
  73. return i1
  74. }
  75. func NewDecimalFromBigFloat(bigFloat *big.Float) (*DmDecimal, error) {
  76. return newDecimal(bigFloat, int(bigFloat.Prec()), int(bigFloat.Prec()))
  77. }
  78. func (d DmDecimal) ToBigFloat() *big.Float {
  79. if d.isZero() {
  80. return big.NewFloat(0.0)
  81. }
  82. var digits = d.digits
  83. if d.sign < 0 {
  84. digits = "-" + digits
  85. }
  86. f1, ok := new(big.Float).SetString(digits)
  87. if !ok {
  88. return nil
  89. }
  90. if d.weight > 0 {
  91. f2, ok := new(big.Float).SetString("1" + strings.Repeat("0", d.weight))
  92. if !ok {
  93. return nil
  94. }
  95. f1.Mul(f1, f2)
  96. } else if d.weight < 0 {
  97. f2, ok := new(big.Float).SetString("1" + strings.Repeat("0", -d.weight))
  98. if !ok {
  99. return nil
  100. }
  101. f1.Quo(f1, f2)
  102. }
  103. return f1
  104. }
  105. func NewDecimalFromString(s string) (*DmDecimal, error) {
  106. num, ok := new(big.Float).SetString(strings.TrimSpace(s))
  107. if !ok {
  108. return nil, ECGO_DATA_CONVERTION_ERROR.throw()
  109. }
  110. return NewDecimalFromBigFloat(num)
  111. }
  112. func (d DmDecimal) String() string {
  113. if d.isZero() {
  114. return "0"
  115. }
  116. digitsStr := d.digits
  117. if d.weight > 0 {
  118. digitsStr = digitsStr + strings.Repeat("0", d.weight)
  119. } else if d.weight < 0 {
  120. if len(digitsStr) < -d.weight {
  121. digitsStr = strings.Repeat("0", -d.weight-len(digitsStr)+1) + digitsStr
  122. }
  123. indexOfDot := len(digitsStr) + d.weight
  124. digitsStr = digitsStr[:indexOfDot] + "." + digitsStr[indexOfDot:]
  125. }
  126. if digitsStr[0] == '0' && digitsStr[1] != '.' {
  127. digitsStr = digitsStr[1:]
  128. }
  129. if digitsStr[len(digitsStr)-1] == '0' && strings.IndexRune(digitsStr, '.') >= 0 {
  130. digitsStr = digitsStr[0 : len(digitsStr)-1]
  131. }
  132. if d.sign < 0 {
  133. digitsStr = "-" + digitsStr
  134. }
  135. return digitsStr
  136. }
  137. func (d DmDecimal) Sign() int {
  138. return d.sign
  139. }
  140. func (dest *DmDecimal) Scan(src interface{}) error {
  141. if dest == nil {
  142. return ECGO_STORE_IN_NIL_POINTER.throw()
  143. }
  144. switch src := src.(type) {
  145. case nil:
  146. *dest = *new(DmDecimal)
  147. (*dest).Valid = false
  148. return nil
  149. case int, int8, int16, int32, int64:
  150. d, err := NewDecimalFromInt64(reflect.ValueOf(src).Int())
  151. if err != nil {
  152. return err
  153. }
  154. *dest = *d
  155. return nil
  156. case uint, uint8, uint16, uint32, uint64:
  157. d, err := NewDecimalFromBigInt(new(big.Int).SetUint64(reflect.ValueOf(src).Uint()))
  158. if err != nil {
  159. return err
  160. }
  161. *dest = *d
  162. return nil
  163. case float32, float64:
  164. d, err := NewDecimalFromFloat64(reflect.ValueOf(src).Float())
  165. if err != nil {
  166. return err
  167. }
  168. *dest = *d
  169. return nil
  170. case string:
  171. d, err := NewDecimalFromString(src)
  172. if err != nil {
  173. return err
  174. }
  175. *dest = *d
  176. return nil
  177. case *DmDecimal:
  178. *dest = *src
  179. return nil
  180. default:
  181. return UNSUPPORTED_SCAN
  182. }
  183. }
  184. func (d DmDecimal) Value() (driver.Value, error) {
  185. if !d.Valid {
  186. return nil, nil
  187. }
  188. return d, nil
  189. }
  190. func newDecimal(dec interface{}, prec int, scale int) (*DmDecimal, error) {
  191. d := &DmDecimal{
  192. prec: prec,
  193. scale: scale,
  194. Valid: true,
  195. }
  196. if isFloat(DECIMAL, scale) {
  197. d.prec = getFloatPrec(prec)
  198. d.scale = -1
  199. }
  200. switch de := dec.(type) {
  201. case *big.Int:
  202. d.sign = de.Sign()
  203. if d.isZero() {
  204. return d, nil
  205. }
  206. str := de.String()
  207. if d.sign < 0 {
  208. str = str[1:]
  209. }
  210. if err := checkPrec(len(str), prec); err != nil {
  211. return d, err
  212. }
  213. i := 0
  214. istart := len(str) - 1
  215. for i = istart; i > 0; i-- {
  216. if str[i] != '0' {
  217. break
  218. }
  219. }
  220. str = str[:i+1]
  221. d.weight += istart - i
  222. if isOdd(d.weight) {
  223. str += "0"
  224. d.weight -= 1
  225. }
  226. if isOdd(len(str)) {
  227. str = "0" + str
  228. }
  229. d.digits = str
  230. case *big.Float:
  231. d.sign = de.Sign()
  232. if d.isZero() {
  233. return d, nil
  234. }
  235. str := de.Text('f', -1)
  236. if d.sign < 0 {
  237. str = str[1:]
  238. }
  239. pointIndex := strings.IndexByte(str, '.')
  240. i, istart, length := 0, 0, len(str)
  241. if pointIndex != -1 {
  242. if str[0] == '0' {
  243. istart = 2
  244. for i = istart; i < length; i++ {
  245. if str[i] != '0' {
  246. break
  247. }
  248. }
  249. str = str[i:]
  250. d.weight -= i - istart + len(str)
  251. } else {
  252. str = str[:pointIndex] + str[pointIndex+1:]
  253. d.weight -= length - pointIndex - 1
  254. }
  255. }
  256. length = len(str)
  257. istart = length - 1
  258. for i = istart; i > 0; i-- {
  259. if str[i] != '0' {
  260. break
  261. }
  262. }
  263. str = str[:i+1] + str[length:]
  264. d.weight += istart - i
  265. if isOdd(d.weight) {
  266. str += "0"
  267. d.weight -= 1
  268. }
  269. if isOdd(len(str)) {
  270. str = "0" + str
  271. }
  272. d.digits = str
  273. case []byte:
  274. return decodeDecimal(de, prec, scale)
  275. }
  276. return d, nil
  277. }
  278. func (d DmDecimal) encodeDecimal() ([]byte, error) {
  279. if d.isZero() {
  280. return []byte{byte(FLAG_ZERO)}, nil
  281. }
  282. exp := (d.weight+len(d.digits))/2 - 1
  283. if exp > EXP_MAX || exp < EXP_MIN {
  284. return nil, ECGO_DATA_TOO_LONG.throw()
  285. }
  286. validLen := len(d.digits)/2 + 1
  287. if d.sign < 0 && validLen >= XDEC_SIZE {
  288. validLen = XDEC_SIZE - 1
  289. } else if validLen > XDEC_SIZE {
  290. validLen = XDEC_SIZE
  291. }
  292. retLen := validLen
  293. if d.sign < 0 {
  294. retLen = validLen + 1
  295. }
  296. retBytes := make([]byte, retLen)
  297. if d.sign > 0 {
  298. retBytes[0] = byte(exp + FLAG_POSITIVE)
  299. } else {
  300. retBytes[0] = byte(FLAG_NEGTIVE - exp)
  301. }
  302. ibytes := 1
  303. for ichar := 0; ibytes < validLen; {
  304. digit1, err := strconv.Atoi(string(d.digits[ichar]))
  305. if err != nil {
  306. return nil, err
  307. }
  308. ichar++
  309. digit2, err := strconv.Atoi(string(d.digits[ichar]))
  310. ichar++
  311. if err != nil {
  312. return nil, err
  313. }
  314. digit := digit1*10 + digit2
  315. if d.sign > 0 {
  316. retBytes[ibytes] = byte(digit + NUM_POSITIVE)
  317. } else {
  318. retBytes[ibytes] = byte(NUM_NEGTIVE - digit)
  319. }
  320. ibytes++
  321. }
  322. if d.sign < 0 && ibytes < retLen {
  323. retBytes[ibytes] = 0x66
  324. ibytes++
  325. }
  326. if ibytes < retLen {
  327. retBytes[ibytes] = 0x00
  328. }
  329. return retBytes, nil
  330. }
  331. func decodeDecimal(values []byte, prec int, scale int) (*DmDecimal, error) {
  332. var decimal = &DmDecimal{
  333. prec: prec,
  334. scale: scale,
  335. sign: 0,
  336. weight: 0,
  337. Valid: true,
  338. }
  339. if values == nil || len(values) == 0 || len(values) > XDEC_SIZE {
  340. return nil, ECGO_FATAL_ERROR.throw()
  341. }
  342. if values[0] == byte(FLAG_ZERO) || len(values) == 1 {
  343. return decimal, nil
  344. }
  345. if values[0]&byte(FLAG_ZERO) != 0 {
  346. decimal.sign = 1
  347. } else {
  348. decimal.sign = -1
  349. }
  350. var flag = int(Dm_build_1.Dm_build_121(values, 0))
  351. var exp int
  352. if decimal.sign > 0 {
  353. exp = flag - FLAG_POSITIVE
  354. } else {
  355. exp = FLAG_NEGTIVE - flag
  356. }
  357. var digit = 0
  358. var sf = ""
  359. for ival := 1; ival < len(values); ival++ {
  360. if decimal.sign > 0 {
  361. digit = int(values[ival]) - NUM_POSITIVE
  362. } else {
  363. digit = NUM_NEGTIVE - int(values[ival])
  364. }
  365. if digit < 0 || digit > 99 {
  366. break
  367. }
  368. if digit < 10 {
  369. sf += "0"
  370. }
  371. sf += strconv.Itoa(digit)
  372. }
  373. decimal.digits = sf
  374. decimal.weight = exp*2 - (len(decimal.digits) - 2)
  375. return decimal, nil
  376. }
  377. func (d DmDecimal) isZero() bool {
  378. return d.sign == 0
  379. }
  380. func checkPrec(len int, prec int) error {
  381. if prec > 0 && len > prec || len > XDEC_MAX_PREC {
  382. return ECGO_DATA_TOO_LONG.throw()
  383. }
  384. return nil
  385. }
  386. func isOdd(val int) bool {
  387. return val%2 != 0
  388. }
  389. func (d *DmDecimal) checkValid() error {
  390. if !d.Valid {
  391. return ECGO_IS_NULL.throw()
  392. }
  393. return nil
  394. }