r.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. /*
  2. * Copyright (c) 2000-2018, 达梦数据库有限公司.
  3. * All rights reserved.
  4. */
  5. package dm
  6. import (
  7. "database/sql/driver"
  8. "math"
  9. "strconv"
  10. "strings"
  11. "gitee.com/chunanyong/dm/util"
  12. )
  13. const (
  14. QUA_Y = 0
  15. QUA_YM = 1
  16. QUA_MO = 2
  17. )
  18. type DmIntervalYM struct {
  19. leadScale int
  20. isLeadScaleSet bool
  21. _type byte
  22. years int
  23. months int
  24. scaleForSvr int
  25. Valid bool
  26. }
  27. func newDmIntervalYM() *DmIntervalYM {
  28. return &DmIntervalYM{
  29. Valid: true,
  30. }
  31. }
  32. func NewDmIntervalYMByString(str string) (ym *DmIntervalYM, err error) {
  33. defer func() {
  34. if p := recover(); p != nil {
  35. err = ECGO_INVALID_TIME_INTERVAL.throw()
  36. }
  37. }()
  38. ym = newDmIntervalYM()
  39. ym.isLeadScaleSet = false
  40. if err = ym.parseIntervYMString(strings.TrimSpace(str)); err != nil {
  41. return nil, err
  42. }
  43. return ym, nil
  44. }
  45. func newDmIntervalYMByBytes(bytes []byte) *DmIntervalYM {
  46. ym := newDmIntervalYM()
  47. ym.scaleForSvr = int(Dm_build_1.Dm_build_103(bytes, 8))
  48. ym.leadScale = (ym.scaleForSvr >> 4) & 0x0000000F
  49. ym._type = bytes[9]
  50. switch ym._type {
  51. case QUA_Y:
  52. ym.years = int(Dm_build_1.Dm_build_103(bytes, 0))
  53. case QUA_YM:
  54. ym.years = int(Dm_build_1.Dm_build_103(bytes, 0))
  55. ym.months = int(Dm_build_1.Dm_build_103(bytes, 4))
  56. case QUA_MO:
  57. ym.months = int(Dm_build_1.Dm_build_103(bytes, 4))
  58. }
  59. return ym
  60. }
  61. func (ym *DmIntervalYM) GetYear() int {
  62. return ym.years
  63. }
  64. func (ym *DmIntervalYM) GetMonth() int {
  65. return ym.months
  66. }
  67. func (ym *DmIntervalYM) GetYMType() byte {
  68. return ym._type
  69. }
  70. func (ym *DmIntervalYM) String() string {
  71. if !ym.Valid {
  72. return ""
  73. }
  74. str := "INTERVAL "
  75. var year, month string
  76. var l int
  77. var destLen int
  78. switch ym._type {
  79. case QUA_Y:
  80. year = strconv.FormatInt(int64(math.Abs(float64(ym.years))), 10)
  81. if ym.years < 0 {
  82. str += "-"
  83. }
  84. if ym.leadScale > len(year) {
  85. l = len(year)
  86. destLen = ym.leadScale
  87. for destLen > l {
  88. year = "0" + year
  89. destLen--
  90. }
  91. }
  92. str += "'" + year + "' YEAR(" + strconv.FormatInt(int64(ym.leadScale), 10) + ")"
  93. case QUA_YM:
  94. year = strconv.FormatInt(int64(math.Abs(float64(ym.years))), 10)
  95. month = strconv.FormatInt(int64(math.Abs(float64(ym.months))), 10)
  96. if ym.years < 0 || ym.months < 0 {
  97. str += "-"
  98. }
  99. if ym.leadScale > len(year) {
  100. l = len(year)
  101. destLen = ym.leadScale
  102. for destLen > l {
  103. year = "0" + year
  104. destLen--
  105. }
  106. }
  107. if len(month) < 2 {
  108. month = "0" + month
  109. }
  110. str += "'" + year + "-" + month + "' YEAR(" + strconv.FormatInt(int64(ym.leadScale), 10) + ") TO MONTH"
  111. case QUA_MO:
  112. month = strconv.FormatInt(int64(math.Abs(float64(ym.months))), 10)
  113. if ym.months < 0 {
  114. str += "-"
  115. }
  116. if ym.leadScale > len(month) {
  117. l = len(month)
  118. destLen = ym.leadScale
  119. for destLen > l {
  120. month = "0" + month
  121. destLen--
  122. }
  123. }
  124. str += "'" + month + "' MONTH(" + strconv.FormatInt(int64(ym.leadScale), 10) + ")"
  125. }
  126. return str
  127. }
  128. func (dest *DmIntervalYM) Scan(src interface{}) error {
  129. if dest == nil {
  130. return ECGO_STORE_IN_NIL_POINTER.throw()
  131. }
  132. switch src := src.(type) {
  133. case nil:
  134. *dest = *new(DmIntervalYM)
  135. (*dest).Valid = false
  136. return nil
  137. case *DmIntervalYM:
  138. *dest = *src
  139. return nil
  140. case string:
  141. ret, err := NewDmIntervalYMByString(src)
  142. if err != nil {
  143. return err
  144. }
  145. *dest = *ret
  146. return nil
  147. default:
  148. return UNSUPPORTED_SCAN
  149. }
  150. }
  151. func (ym DmIntervalYM) Value() (driver.Value, error) {
  152. if !ym.Valid {
  153. return nil, nil
  154. }
  155. return ym, nil
  156. }
  157. func (ym *DmIntervalYM) parseIntervYMString(str string) error {
  158. str = strings.ToUpper(str)
  159. ret := strings.Split(str, " ")
  160. l := len(ret)
  161. if l < 3 || !util.StringUtil.EqualsIgnoreCase(ret[0], "INTERVAL") || !(strings.HasPrefix(ret[2], "YEAR") || strings.HasPrefix(ret[2], "MONTH")) {
  162. return ECGO_INVALID_TIME_INTERVAL.throw()
  163. }
  164. ym._type = QUA_YM
  165. yearId := strings.Index(str, "YEAR")
  166. monthId := strings.Index(str, "MONTH")
  167. toId := strings.Index(str, "TO")
  168. var err error
  169. if toId == -1 {
  170. if yearId != -1 && monthId == -1 {
  171. ym._type = QUA_Y
  172. ym.leadScale, err = ym.getLeadPrec(str, yearId)
  173. if err != nil {
  174. return err
  175. }
  176. } else if monthId != -1 && yearId == -1 {
  177. ym._type = QUA_MO
  178. ym.leadScale, err = ym.getLeadPrec(str, monthId)
  179. if err != nil {
  180. return err
  181. }
  182. } else {
  183. return ECGO_INVALID_TIME_INTERVAL.throw()
  184. }
  185. } else {
  186. if yearId == -1 || monthId == -1 {
  187. return ECGO_INVALID_TIME_INTERVAL.throw()
  188. }
  189. ym._type = QUA_YM
  190. ym.leadScale, err = ym.getLeadPrec(str, yearId)
  191. if err != nil {
  192. return err
  193. }
  194. }
  195. ym.scaleForSvr = (int(ym._type) << 8) + (ym.leadScale << 4)
  196. timeVals, err := ym.getTimeValue(ret[1], int(ym._type))
  197. if err != nil {
  198. return err
  199. }
  200. ym.years = timeVals[0]
  201. ym.months = timeVals[1]
  202. return ym.checkScale(ym.leadScale)
  203. }
  204. func (ym *DmIntervalYM) getLeadPrec(str string, startIndex int) (int, error) {
  205. if ym.isLeadScaleSet {
  206. return ym.leadScale, nil
  207. }
  208. leftBtId := strings.Index(str[startIndex:], "(")
  209. rightBtId := strings.Index(str[startIndex:], ")")
  210. leadPrec := 0
  211. if rightBtId == -1 && leftBtId == -1 {
  212. leftBtId += startIndex
  213. rightBtId += startIndex
  214. l := strings.Index(str, "'")
  215. var r int
  216. var dataStr string
  217. if l != -1 {
  218. r = strings.Index(str[l+1:], "'")
  219. if r != -1 {
  220. r += l + 1
  221. }
  222. } else {
  223. r = -1
  224. }
  225. if r != -1 {
  226. dataStr = strings.TrimSpace(str[l+1 : r])
  227. } else {
  228. dataStr = ""
  229. }
  230. if dataStr != "" {
  231. sign := dataStr[0]
  232. if sign == '+' || sign == '-' {
  233. dataStr = strings.TrimSpace(dataStr[1:])
  234. }
  235. end := strings.Index(dataStr, "-")
  236. if end != -1 {
  237. dataStr = dataStr[:end]
  238. }
  239. leadPrec = len(dataStr)
  240. } else {
  241. leadPrec = 2
  242. }
  243. } else if rightBtId != -1 && leftBtId != -1 && rightBtId > leftBtId+1 {
  244. leftBtId += startIndex
  245. rightBtId += startIndex
  246. strPrec := strings.TrimSpace(str[leftBtId+1 : rightBtId])
  247. temp, err := strconv.ParseInt(strPrec, 10, 32)
  248. if err != nil {
  249. return 0, err
  250. }
  251. leadPrec = int(temp)
  252. } else {
  253. return 0, ECGO_INVALID_TIME_INTERVAL.throw()
  254. }
  255. return leadPrec, nil
  256. }
  257. func (ym *DmIntervalYM) checkScale(prec int) error {
  258. switch ym._type {
  259. case QUA_Y:
  260. if prec < len(strconv.FormatInt(int64(math.Abs(float64(ym.years))), 10)) {
  261. return ECGO_INVALID_TIME_INTERVAL.throw()
  262. }
  263. case QUA_YM:
  264. if prec < len(strconv.FormatInt(int64(math.Abs(float64(ym.years))), 10)) {
  265. return ECGO_INVALID_TIME_INTERVAL.throw()
  266. }
  267. if int64(math.Abs(float64(ym.months))) > 11 {
  268. return ECGO_INVALID_TIME_INTERVAL.throw()
  269. }
  270. case QUA_MO:
  271. if prec < len(strconv.FormatInt(int64(math.Abs(float64(ym.months))), 10)) {
  272. return ECGO_INVALID_TIME_INTERVAL.throw()
  273. }
  274. }
  275. return nil
  276. }
  277. func (ym *DmIntervalYM) getTimeValue(subStr string, _type int) ([]int, error) {
  278. hasQuate := false
  279. if subStr[0] == '\'' && subStr[len(subStr)-1] == '\'' {
  280. hasQuate = true
  281. subStr = strings.TrimSpace(subStr[1 : len(subStr)-1])
  282. }
  283. negative := false
  284. if strings.Index(subStr, "-") == 0 {
  285. negative = true
  286. subStr = subStr[1:]
  287. } else if strings.Index(subStr, "+") == 0 {
  288. negative = false
  289. subStr = subStr[1:]
  290. }
  291. if subStr[0] == '\'' && subStr[len(subStr)-1] == '\'' {
  292. hasQuate = true
  293. subStr = strings.TrimSpace(subStr[1 : len(subStr)-1])
  294. }
  295. if !hasQuate {
  296. return nil, ECGO_INVALID_TIME_INTERVAL.throw()
  297. }
  298. lastSignIndex := strings.LastIndex(subStr, "-")
  299. list := make([]string, 2)
  300. if lastSignIndex == -1 || lastSignIndex == 0 {
  301. list[0] = subStr
  302. list[1] = ""
  303. } else {
  304. list[0] = subStr[0:lastSignIndex]
  305. list[1] = subStr[lastSignIndex+1:]
  306. }
  307. var yearVal, monthVal int64
  308. var err error
  309. if ym._type == QUA_YM {
  310. yearVal, err = strconv.ParseInt(list[0], 10, 32)
  311. if err != nil {
  312. return nil, err
  313. }
  314. if util.StringUtil.EqualsIgnoreCase(list[1], "") {
  315. monthVal = 0
  316. } else {
  317. monthVal, err = strconv.ParseInt(list[1], 10, 32)
  318. if err != nil {
  319. return nil, err
  320. }
  321. }
  322. if negative {
  323. yearVal *= -1
  324. monthVal *= -1
  325. }
  326. if yearVal > int64(math.Pow10(ym.leadScale))-1 || yearVal < 1-int64(math.Pow10(ym.leadScale)) {
  327. return nil, ECGO_INVALID_TIME_INTERVAL.throw()
  328. }
  329. } else if ym._type == QUA_Y {
  330. yearVal, err = strconv.ParseInt(list[0], 10, 32)
  331. if err != nil {
  332. return nil, err
  333. }
  334. monthVal = 0
  335. if negative {
  336. yearVal *= -1
  337. }
  338. if yearVal > int64(math.Pow10(ym.leadScale))-1 || yearVal < 1-int64(math.Pow10(ym.leadScale)) {
  339. return nil, ECGO_INVALID_TIME_INTERVAL.throw()
  340. }
  341. } else {
  342. yearVal = 0
  343. monthVal, err = strconv.ParseInt(list[0], 10, 32)
  344. if err != nil {
  345. return nil, err
  346. }
  347. if negative {
  348. monthVal *= -1
  349. }
  350. if monthVal > int64(math.Pow10(ym.leadScale))-1 || monthVal < 1-int64(math.Pow10(ym.leadScale)) {
  351. return nil, ECGO_INVALID_TIME_INTERVAL.throw()
  352. }
  353. }
  354. ret := make([]int, 2)
  355. ret[0] = int(yearVal)
  356. ret[1] = int(monthVal)
  357. return ret, nil
  358. }
  359. func (ym *DmIntervalYM) encode(scale int) ([]byte, error) {
  360. if scale == 0 {
  361. scale = ym.scaleForSvr
  362. }
  363. year, month := ym.years, ym.months
  364. if err := ym.checkScale(ym.leadScale); err != nil {
  365. return nil, err
  366. }
  367. if scale != ym.scaleForSvr {
  368. convertYM, err := ym.convertTo(scale)
  369. if err != nil {
  370. return nil, err
  371. }
  372. year = convertYM.years
  373. month = convertYM.months
  374. } else {
  375. if err := ym.checkScale(ym.leadScale); err != nil {
  376. return nil, err
  377. }
  378. }
  379. bytes := make([]byte, 12)
  380. Dm_build_1.Dm_build_17(bytes, 0, int32(year))
  381. Dm_build_1.Dm_build_17(bytes, 4, int32(month))
  382. Dm_build_1.Dm_build_17(bytes, 8, int32(scale))
  383. return bytes, nil
  384. }
  385. func (ym *DmIntervalYM) convertTo(scale int) (*DmIntervalYM, error) {
  386. destType := (scale & 0x0000FF00) >> 8
  387. leadPrec := (scale >> 4) & 0x0000000F
  388. totalMonths := ym.years*12 + ym.months
  389. year := 0
  390. month := 0
  391. switch destType {
  392. case QUA_Y:
  393. year = totalMonths / 12
  394. if totalMonths%12 >= 6 {
  395. year++
  396. } else if totalMonths%12 <= -6 {
  397. year--
  398. }
  399. if leadPrec < len(strconv.Itoa(int(math.Abs(float64(year))))) {
  400. return nil, ECGO_INVALID_TIME_INTERVAL.throw()
  401. }
  402. case QUA_YM:
  403. year = totalMonths / 12
  404. month = totalMonths % 12
  405. if leadPrec < len(strconv.Itoa(int(math.Abs(float64(year))))) {
  406. return nil, ECGO_INVALID_TIME_INTERVAL.throw()
  407. }
  408. case QUA_MO:
  409. month = totalMonths
  410. if leadPrec < len(strconv.Itoa(int(math.Abs(float64(month))))) {
  411. return nil, ECGO_INVALID_TIME_INTERVAL.throw()
  412. }
  413. }
  414. return &DmIntervalYM{
  415. _type: byte(destType),
  416. years: year,
  417. months: month,
  418. scaleForSvr: scale,
  419. leadScale: (scale >> 4) & 0x0000000F,
  420. Valid: true,
  421. }, nil
  422. }
  423. func (ym *DmIntervalYM) checkValid() error {
  424. if !ym.Valid {
  425. return ECGO_IS_NULL.throw()
  426. }
  427. return nil
  428. }