chencheng 2 سال پیش
کامیت
1416c00068
78فایلهای تغییر یافته به همراه30582 افزوده شده و 0 حذف شده
  1. 2 0
      .gitignore
  2. 49 0
      README.md
  3. 3 0
      VERSION
  4. 819 0
      a.go
  5. 45 0
      b.go
  6. 495 0
      c.go
  7. 206 0
      d.go
  8. 547 0
      e.go
  9. 47 0
      f.go
  10. 2158 0
      g.go
  11. 8 0
      go.mod
  12. 5 0
      go.sum
  13. 923 0
      h.go
  14. 917 0
      i.go
  15. 48 0
      i18n/zj.go
  16. 240 0
      i18n/zk.go
  17. 240 0
      i18n/zl.go
  18. 28 0
      i18n/zm.go
  19. 270 0
      j.go
  20. 290 0
      k.go
  21. 272 0
      l.go
  22. 891 0
      m.go
  23. 895 0
      n.go
  24. 443 0
      o.go
  25. 86 0
      p.go
  26. 46 0
      parser/zt.go
  27. 1206 0
      parser/zu.go
  28. 1451 0
      q.go
  29. 490 0
      r.go
  30. 54 0
      s.go
  31. 30 0
      security/zy.go
  32. 11 0
      security/zz.go
  33. 87 0
      security/zza.go
  34. 64 0
      security/zzb.go
  35. 69 0
      security/zzc.go
  36. 114 0
      security/zzd.go
  37. 211 0
      security/zze.go
  38. 142 0
      security/zzf.go
  39. 96 0
      security/zzg_darwin.go
  40. 96 0
      security/zzg_linux.go
  41. 83 0
      security/zzh_windows.go
  42. 50 0
      security/zzi.go
  43. 522 0
      t.go
  44. 1514 0
      u.go
  45. 38 0
      util/zzq.go
  46. 75 0
      util/zzr.go
  47. 47 0
      util/zzs.go
  48. 218 0
      util/zzt.go
  49. 142 0
      v.go
  50. 226 0
      w.go
  51. 192 0
      x.go
  52. 148 0
      y.go
  53. 65 0
      z.go
  54. 137 0
      za.go
  55. 307 0
      zb.go
  56. 443 0
      zc.go
  57. 403 0
      zd.go
  58. 871 0
      ze.go
  59. 497 0
      zf.go
  60. 310 0
      zg.go
  61. 607 0
      zh.go
  62. 1017 0
      zi.go
  63. 137 0
      zn.go
  64. 19 0
      zo.go
  65. 124 0
      zp.go
  66. 2930 0
      zq.go
  67. 205 0
      zr.go
  68. 882 0
      zs.go
  69. 124 0
      zv.go
  70. 220 0
      zw.go
  71. 421 0
      zx.go
  72. 108 0
      zzj.go
  73. 320 0
      zzk.go
  74. 44 0
      zzl.go
  75. 441 0
      zzm.go
  76. 449 0
      zzn.go
  77. 1389 0
      zzo.go
  78. 763 0
      zzp.go

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
+# 默认忽略的文件
+/.idea/

+ 49 - 0
README.md

@@ -0,0 +1,49 @@
+# dm
+
+### 介绍
+``` 
+go get gitee.com/chunanyong/dm 
+```  
+达梦数据库官方Go驱动,本项目和官方驱动版本同步,方便go mod 使用.  
+安装达梦数据库(版本>=8.1.1.126),安装目录下 drivers/go/dm-go-driver.zip    
+达梦官方文档:https://eco.dameng.com/docs/zh-cn/app-dev/go-go.html    
+资源下载:https://eco.dameng.com/download/    
+达梦官方Go驱动包:https://package.dameng.com/eco/adapter/resource/go/dm-go-driver.zip  
+达梦官方论坛(提交bug):https://eco.dameng.com/community/question  
+
+### zorm  
+Go轻量ORM https://gitee.com/chunanyong/zorm 原生支持达梦数据库  
+
+### DSN  
+dm://userName:password@127.0.0.1:5236?schema=DBName  
+用户名(userName)默认就是数据库的名称,达梦用户模式和数据库名称是对应的,也可以通过schema参数指定数据库  
+建议达梦使用UTF-8字符编码,不区分大小写,建表语句的字段名不要带""双引号      
+
+### bug
+- 达梦开启等保参数 COMM_ENCRYPT_NAME = AES128_ECB,导致连接异常
+
+### 版本号  
+Go三段位版本号和达梦四段位版本号不兼容,统一使用1.达梦主版本号.发布的小版本号,具体查看标签的备注  
+
+* v1.8.11 来自 达梦8.1.2.192
+* v1.8.10 来自 达梦8.1.2.174
+* v1.8.9  来自 达梦8.1.2.162
+* v1.8.8  来自 达梦8.1.2.138
+* v1.8.7  来自 达梦8.1.2.128 
+* v1.8.6  来自 达梦8.1.2.114 
+* v1.8.5  来自 达梦8.1.2.94    
+* v1.8.4  来自 达梦8.1.2.84 
+* v1.8.3  来自 达梦8.1.2.38  
+* v1.8.2  来自 达梦8.1.2.18  
+* v1.8.1  来自 达梦8.1.1.190  
+* v1.8.0  来自 达梦8.1.1.126  
+
+
+
+
+    
+    
+
+
+
+

+ 3 - 0
VERSION

@@ -0,0 +1,3 @@
+#8.1.2.192
+#2023.01.05
+#14827

+ 819 - 0
a.go

@@ -0,0 +1,819 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"bytes"
+	"crypto/tls"
+	"fmt"
+	"net"
+	"strconv"
+	"time"
+	"unicode/utf8"
+
+	"gitee.com/chunanyong/dm/security"
+)
+
+const (
+	Dm_build_695 = 8192
+	Dm_build_696 = 2 * time.Second
+)
+
+type dm_build_697 struct {
+	dm_build_698 *net.TCPConn
+	dm_build_699 *tls.Conn
+	dm_build_700 *Dm_build_361
+	dm_build_701 *DmConnection
+	dm_build_702 security.Cipher
+	dm_build_703 bool
+	dm_build_704 bool
+	dm_build_705 *security.DhKey
+
+	dm_build_706 bool
+	dm_build_707 string
+	dm_build_708 bool
+}
+
+func dm_build_709(dm_build_710 *DmConnection) (*dm_build_697, error) {
+	dm_build_711, dm_build_712 := dm_build_714(dm_build_710.dmConnector.host+":"+strconv.Itoa(int(dm_build_710.dmConnector.port)), time.Duration(dm_build_710.dmConnector.socketTimeout)*time.Second)
+	if dm_build_712 != nil {
+		return nil, dm_build_712
+	}
+
+	dm_build_713 := dm_build_697{}
+	dm_build_713.dm_build_698 = dm_build_711
+	dm_build_713.dm_build_700 = Dm_build_364(Dm_build_976)
+	dm_build_713.dm_build_701 = dm_build_710
+	dm_build_713.dm_build_703 = false
+	dm_build_713.dm_build_704 = false
+	dm_build_713.dm_build_706 = false
+	dm_build_713.dm_build_707 = ""
+	dm_build_713.dm_build_708 = false
+	dm_build_710.Access = &dm_build_713
+
+	return &dm_build_713, nil
+}
+
+func dm_build_714(dm_build_715 string, dm_build_716 time.Duration) (*net.TCPConn, error) {
+	dm_build_717, dm_build_718 := net.DialTimeout("tcp", dm_build_715, dm_build_716)
+	if dm_build_718 != nil {
+		return nil, ECGO_COMMUNITION_ERROR.addDetail("\tdial address: " + dm_build_715).throw()
+	}
+
+	if tcpConn, ok := dm_build_717.(*net.TCPConn); ok {
+
+		tcpConn.SetKeepAlive(true)
+		tcpConn.SetKeepAlivePeriod(Dm_build_696)
+		tcpConn.SetNoDelay(true)
+
+		return tcpConn, nil
+	}
+
+	return nil, nil
+}
+
+func (dm_build_720 *dm_build_697) dm_build_719(dm_build_721 dm_build_1097) bool {
+	var dm_build_722 = dm_build_720.dm_build_701.dmConnector.compress
+	if dm_build_721.dm_build_1112() == Dm_build_1004 || dm_build_722 == Dm_build_1053 {
+		return false
+	}
+
+	if dm_build_722 == Dm_build_1051 {
+		return true
+	} else if dm_build_722 == Dm_build_1052 {
+		return !dm_build_720.dm_build_701.Local && dm_build_721.dm_build_1110() > Dm_build_1050
+	}
+
+	return false
+}
+
+func (dm_build_724 *dm_build_697) dm_build_723(dm_build_725 dm_build_1097) bool {
+	var dm_build_726 = dm_build_724.dm_build_701.dmConnector.compress
+	if dm_build_725.dm_build_1112() == Dm_build_1004 || dm_build_726 == Dm_build_1053 {
+		return false
+	}
+
+	if dm_build_726 == Dm_build_1051 {
+		return true
+	} else if dm_build_726 == Dm_build_1052 {
+		return dm_build_724.dm_build_700.Dm_build_628(Dm_build_1012) == 1
+	}
+
+	return false
+}
+
+func (dm_build_728 *dm_build_697) dm_build_727(dm_build_729 dm_build_1097) (err error) {
+	defer func() {
+		if p := recover(); p != nil {
+			if _, ok := p.(string); ok {
+				err = ECGO_COMMUNITION_ERROR.addDetail("\t" + p.(string)).throw()
+			} else {
+				err = fmt.Errorf("internal error: %v", p)
+			}
+		}
+	}()
+
+	dm_build_731 := dm_build_729.dm_build_1110()
+
+	if dm_build_731 > 0 {
+
+		if dm_build_728.dm_build_719(dm_build_729) {
+			var retBytes, err = Compress(dm_build_728.dm_build_700, Dm_build_1005, int(dm_build_731), int(dm_build_728.dm_build_701.dmConnector.compressID))
+			if err != nil {
+				return err
+			}
+
+			dm_build_728.dm_build_700.Dm_build_375(Dm_build_1005)
+
+			dm_build_728.dm_build_700.Dm_build_416(dm_build_731)
+
+			dm_build_728.dm_build_700.Dm_build_444(retBytes)
+
+			dm_build_729.dm_build_1111(int32(len(retBytes)) + ULINT_SIZE)
+
+			dm_build_728.dm_build_700.Dm_build_548(Dm_build_1012, 1)
+		}
+
+		if dm_build_728.dm_build_704 {
+			dm_build_731 = dm_build_729.dm_build_1110()
+			var retBytes = dm_build_728.dm_build_702.Encrypt(dm_build_728.dm_build_700.Dm_build_655(Dm_build_1005, int(dm_build_731)), true)
+
+			dm_build_728.dm_build_700.Dm_build_375(Dm_build_1005)
+
+			dm_build_728.dm_build_700.Dm_build_444(retBytes)
+
+			dm_build_729.dm_build_1111(int32(len(retBytes)))
+		}
+	}
+
+	if dm_build_728.dm_build_700.Dm_build_373() > Dm_build_977 {
+		return ECGO_MSG_TOO_LONG.throw()
+	}
+
+	dm_build_729.dm_build_1106()
+	if dm_build_728.dm_build_959(dm_build_729) {
+		if dm_build_728.dm_build_699 != nil {
+			dm_build_728.dm_build_700.Dm_build_378(0)
+			if _, err := dm_build_728.dm_build_700.Dm_build_397(dm_build_728.dm_build_699); err != nil {
+				return err
+			}
+		}
+	} else {
+		dm_build_728.dm_build_700.Dm_build_378(0)
+		if _, err := dm_build_728.dm_build_700.Dm_build_397(dm_build_728.dm_build_698); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func (dm_build_733 *dm_build_697) dm_build_732(dm_build_734 dm_build_1097) (err error) {
+	defer func() {
+		if p := recover(); p != nil {
+			if _, ok := p.(string); ok {
+				err = ECGO_COMMUNITION_ERROR.addDetail("\t" + p.(string)).throw()
+			} else {
+				err = fmt.Errorf("internal error: %v", p)
+			}
+		}
+	}()
+
+	dm_build_736 := int32(0)
+	if dm_build_733.dm_build_959(dm_build_734) {
+		if dm_build_733.dm_build_699 != nil {
+			dm_build_733.dm_build_700.Dm_build_375(0)
+			if _, err := dm_build_733.dm_build_700.Dm_build_391(dm_build_733.dm_build_699, Dm_build_1005); err != nil {
+				return err
+			}
+
+			dm_build_736 = dm_build_734.dm_build_1110()
+			if dm_build_736 > 0 {
+				if _, err := dm_build_733.dm_build_700.Dm_build_391(dm_build_733.dm_build_699, int(dm_build_736)); err != nil {
+					return err
+				}
+			}
+		}
+	} else {
+
+		dm_build_733.dm_build_700.Dm_build_375(0)
+		if _, err := dm_build_733.dm_build_700.Dm_build_391(dm_build_733.dm_build_698, Dm_build_1005); err != nil {
+			return err
+		}
+		dm_build_736 = dm_build_734.dm_build_1110()
+
+		if dm_build_736 > 0 {
+			if _, err := dm_build_733.dm_build_700.Dm_build_391(dm_build_733.dm_build_698, int(dm_build_736)); err != nil {
+				return err
+			}
+		}
+	}
+
+	dm_build_734.dm_build_1107()
+
+	dm_build_736 = dm_build_734.dm_build_1110()
+	if dm_build_736 <= 0 {
+		return nil
+	}
+
+	if dm_build_733.dm_build_704 {
+		ebytes := dm_build_733.dm_build_700.Dm_build_655(Dm_build_1005, int(dm_build_736))
+		bytes, err := dm_build_733.dm_build_702.Decrypt(ebytes, true)
+		if err != nil {
+			return err
+		}
+		dm_build_733.dm_build_700.Dm_build_375(Dm_build_1005)
+		dm_build_733.dm_build_700.Dm_build_444(bytes)
+		dm_build_734.dm_build_1111(int32(len(bytes)))
+	}
+
+	if dm_build_733.dm_build_723(dm_build_734) {
+
+		dm_build_736 = dm_build_734.dm_build_1110()
+		cbytes := dm_build_733.dm_build_700.Dm_build_655(Dm_build_1005+ULINT_SIZE, int(dm_build_736-ULINT_SIZE))
+		bytes, err := UnCompress(cbytes, int(dm_build_733.dm_build_701.dmConnector.compressID))
+		if err != nil {
+			return err
+		}
+		dm_build_733.dm_build_700.Dm_build_375(Dm_build_1005)
+		dm_build_733.dm_build_700.Dm_build_444(bytes)
+		dm_build_734.dm_build_1111(int32(len(bytes)))
+	}
+	return nil
+}
+
+func (dm_build_738 *dm_build_697) dm_build_737(dm_build_739 dm_build_1097) (dm_build_740 interface{}, dm_build_741 error) {
+	dm_build_741 = dm_build_739.dm_build_1101(dm_build_739)
+	if dm_build_741 != nil {
+		return nil, dm_build_741
+	}
+
+	dm_build_741 = dm_build_738.dm_build_727(dm_build_739)
+	if dm_build_741 != nil {
+		return nil, dm_build_741
+	}
+
+	dm_build_741 = dm_build_738.dm_build_732(dm_build_739)
+	if dm_build_741 != nil {
+		return nil, dm_build_741
+	}
+
+	return dm_build_739.dm_build_1105(dm_build_739)
+}
+
+func (dm_build_743 *dm_build_697) dm_build_742() (*dm_build_1551, error) {
+
+	Dm_build_744 := dm_build_1557(dm_build_743)
+	_, dm_build_745 := dm_build_743.dm_build_737(Dm_build_744)
+	if dm_build_745 != nil {
+		return nil, dm_build_745
+	}
+
+	return Dm_build_744, nil
+}
+
+func (dm_build_747 *dm_build_697) dm_build_746() error {
+
+	dm_build_748 := dm_build_1418(dm_build_747)
+	_, dm_build_749 := dm_build_747.dm_build_737(dm_build_748)
+	if dm_build_749 != nil {
+		return dm_build_749
+	}
+
+	return nil
+}
+
+func (dm_build_751 *dm_build_697) dm_build_750() error {
+
+	var dm_build_752 *dm_build_1551
+	var err error
+	if dm_build_752, err = dm_build_751.dm_build_742(); err != nil {
+		return err
+	}
+
+	if dm_build_751.dm_build_701.sslEncrypt == 2 {
+		if err = dm_build_751.dm_build_955(false); err != nil {
+			return ECGO_INIT_SSL_FAILED.addDetail("\n" + err.Error()).throw()
+		}
+	} else if dm_build_751.dm_build_701.sslEncrypt == 1 {
+		if err = dm_build_751.dm_build_955(true); err != nil {
+			return ECGO_INIT_SSL_FAILED.addDetail("\n" + err.Error()).throw()
+		}
+	}
+
+	if dm_build_751.dm_build_704 || dm_build_751.dm_build_703 {
+		k, err := dm_build_751.dm_build_945()
+		if err != nil {
+			return err
+		}
+		sessionKey := security.ComputeSessionKey(k, dm_build_752.Dm_build_1555)
+		encryptType := dm_build_752.dm_build_1553
+		hashType := int(dm_build_752.Dm_build_1554)
+		if encryptType == -1 {
+			encryptType = security.DES_CFB
+		}
+		if hashType == -1 {
+			hashType = security.MD5
+		}
+		err = dm_build_751.dm_build_948(encryptType, sessionKey, dm_build_751.dm_build_701.dmConnector.cipherPath, hashType)
+		if err != nil {
+			return err
+		}
+	}
+
+	if err := dm_build_751.dm_build_746(); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (dm_build_755 *dm_build_697) Dm_build_754(dm_build_756 *DmStatement) error {
+	dm_build_757 := dm_build_1580(dm_build_755, dm_build_756)
+	_, dm_build_758 := dm_build_755.dm_build_737(dm_build_757)
+	if dm_build_758 != nil {
+		return dm_build_758
+	}
+
+	return nil
+}
+
+func (dm_build_760 *dm_build_697) Dm_build_759(dm_build_761 int32) error {
+	dm_build_762 := dm_build_1590(dm_build_760, dm_build_761)
+	_, dm_build_763 := dm_build_760.dm_build_737(dm_build_762)
+	if dm_build_763 != nil {
+		return dm_build_763
+	}
+
+	return nil
+}
+
+func (dm_build_765 *dm_build_697) Dm_build_764(dm_build_766 *DmStatement, dm_build_767 bool, dm_build_768 int16) (*execRetInfo, error) {
+	dm_build_769 := dm_build_1457(dm_build_765, dm_build_766, dm_build_767, dm_build_768)
+	dm_build_770, dm_build_771 := dm_build_765.dm_build_737(dm_build_769)
+	if dm_build_771 != nil {
+		return nil, dm_build_771
+	}
+	return dm_build_770.(*execRetInfo), nil
+}
+
+func (dm_build_773 *dm_build_697) Dm_build_772(dm_build_774 *DmStatement, dm_build_775 int16) (*execRetInfo, error) {
+	return dm_build_773.Dm_build_764(dm_build_774, false, Dm_build_1057)
+}
+
+func (dm_build_777 *dm_build_697) Dm_build_776(dm_build_778 *DmStatement, dm_build_779 []OptParameter) (*execRetInfo, error) {
+	dm_build_780, dm_build_781 := dm_build_777.dm_build_737(dm_build_1200(dm_build_777, dm_build_778, dm_build_779))
+	if dm_build_781 != nil {
+		return nil, dm_build_781
+	}
+
+	return dm_build_780.(*execRetInfo), nil
+}
+
+func (dm_build_783 *dm_build_697) Dm_build_782(dm_build_784 *DmStatement, dm_build_785 int16) (*execRetInfo, error) {
+	return dm_build_783.Dm_build_764(dm_build_784, true, dm_build_785)
+}
+
+func (dm_build_787 *dm_build_697) Dm_build_786(dm_build_788 *DmStatement, dm_build_789 [][]interface{}) (*execRetInfo, error) {
+	dm_build_790 := dm_build_1232(dm_build_787, dm_build_788, dm_build_789)
+	dm_build_791, dm_build_792 := dm_build_787.dm_build_737(dm_build_790)
+	if dm_build_792 != nil {
+		return nil, dm_build_792
+	}
+	return dm_build_791.(*execRetInfo), nil
+}
+
+func (dm_build_794 *dm_build_697) Dm_build_793(dm_build_795 *DmStatement, dm_build_796 [][]interface{}, dm_build_797 bool) (*execRetInfo, error) {
+	var dm_build_798, dm_build_799 = 0, 0
+	var dm_build_800 = len(dm_build_796)
+	var dm_build_801 [][]interface{}
+	var dm_build_802 = NewExceInfo()
+	dm_build_802.updateCounts = make([]int64, dm_build_800)
+	var dm_build_803 = false
+	for dm_build_798 < dm_build_800 {
+		for dm_build_799 = dm_build_798; dm_build_799 < dm_build_800; dm_build_799++ {
+			paramData := dm_build_796[dm_build_799]
+			bindData := make([]interface{}, dm_build_795.paramCount)
+			dm_build_803 = false
+			for icol := 0; icol < int(dm_build_795.paramCount); icol++ {
+				if dm_build_795.bindParams[icol].ioType == IO_TYPE_OUT {
+					continue
+				}
+				if dm_build_794.dm_build_928(bindData, paramData, icol) {
+					dm_build_803 = true
+					break
+				}
+			}
+
+			if dm_build_803 {
+				break
+			}
+			dm_build_801 = append(dm_build_801, bindData)
+		}
+
+		if dm_build_799 != dm_build_798 {
+			tmpExecInfo, err := dm_build_794.Dm_build_786(dm_build_795, dm_build_801)
+			if err != nil {
+				return nil, err
+			}
+			dm_build_801 = dm_build_801[0:0]
+			dm_build_802.union(tmpExecInfo, dm_build_798, dm_build_799-dm_build_798)
+		}
+
+		if dm_build_799 < dm_build_800 {
+			tmpExecInfo, err := dm_build_794.Dm_build_804(dm_build_795, dm_build_796[dm_build_799], dm_build_797)
+			if err != nil {
+				return nil, err
+			}
+
+			dm_build_797 = true
+			dm_build_802.union(tmpExecInfo, dm_build_799, 1)
+		}
+
+		dm_build_798 = dm_build_799 + 1
+	}
+	for _, i := range dm_build_802.updateCounts {
+		if i > 0 {
+			dm_build_802.updateCount += i
+		}
+	}
+	return dm_build_802, nil
+}
+
+func (dm_build_805 *dm_build_697) Dm_build_804(dm_build_806 *DmStatement, dm_build_807 []interface{}, dm_build_808 bool) (*execRetInfo, error) {
+
+	var dm_build_809 = make([]interface{}, dm_build_806.paramCount)
+	for icol := 0; icol < int(dm_build_806.paramCount); icol++ {
+		if dm_build_806.bindParams[icol].ioType == IO_TYPE_OUT {
+			continue
+		}
+		if dm_build_805.dm_build_928(dm_build_809, dm_build_807, icol) {
+
+			if !dm_build_808 {
+				preExecute := dm_build_1446(dm_build_805, dm_build_806, dm_build_806.bindParams)
+				dm_build_805.dm_build_737(preExecute)
+				dm_build_808 = true
+			}
+
+			dm_build_805.dm_build_934(dm_build_806, dm_build_806.bindParams[icol], icol, dm_build_807[icol].(iOffRowBinder))
+			dm_build_809[icol] = ParamDataEnum_OFF_ROW
+		}
+	}
+
+	var dm_build_810 = make([][]interface{}, 1, 1)
+	dm_build_810[0] = dm_build_809
+
+	dm_build_811 := dm_build_1232(dm_build_805, dm_build_806, dm_build_810)
+	dm_build_812, dm_build_813 := dm_build_805.dm_build_737(dm_build_811)
+	if dm_build_813 != nil {
+		return nil, dm_build_813
+	}
+	return dm_build_812.(*execRetInfo), nil
+}
+
+func (dm_build_815 *dm_build_697) Dm_build_814(dm_build_816 *DmStatement, dm_build_817 int16) (*execRetInfo, error) {
+	dm_build_818 := dm_build_1433(dm_build_815, dm_build_816, dm_build_817)
+
+	dm_build_819, dm_build_820 := dm_build_815.dm_build_737(dm_build_818)
+	if dm_build_820 != nil {
+		return nil, dm_build_820
+	}
+	return dm_build_819.(*execRetInfo), nil
+}
+
+func (dm_build_822 *dm_build_697) Dm_build_821(dm_build_823 *innerRows, dm_build_824 int64) (*execRetInfo, error) {
+	dm_build_825 := dm_build_1338(dm_build_822, dm_build_823, dm_build_824, INT64_MAX)
+	dm_build_826, dm_build_827 := dm_build_822.dm_build_737(dm_build_825)
+	if dm_build_827 != nil {
+		return nil, dm_build_827
+	}
+	return dm_build_826.(*execRetInfo), nil
+}
+
+func (dm_build_829 *dm_build_697) Commit() error {
+	dm_build_830 := dm_build_1185(dm_build_829)
+	_, dm_build_831 := dm_build_829.dm_build_737(dm_build_830)
+	if dm_build_831 != nil {
+		return dm_build_831
+	}
+
+	return nil
+}
+
+func (dm_build_833 *dm_build_697) Rollback() error {
+	dm_build_834 := dm_build_1495(dm_build_833)
+	_, dm_build_835 := dm_build_833.dm_build_737(dm_build_834)
+	if dm_build_835 != nil {
+		return dm_build_835
+	}
+
+	return nil
+}
+
+func (dm_build_837 *dm_build_697) Dm_build_836(dm_build_838 *DmConnection) error {
+	dm_build_839 := dm_build_1500(dm_build_837, dm_build_838.IsoLevel)
+	_, dm_build_840 := dm_build_837.dm_build_737(dm_build_839)
+	if dm_build_840 != nil {
+		return dm_build_840
+	}
+
+	return nil
+}
+
+func (dm_build_842 *dm_build_697) Dm_build_841(dm_build_843 *DmStatement, dm_build_844 string) error {
+	dm_build_845 := dm_build_1190(dm_build_842, dm_build_843, dm_build_844)
+	_, dm_build_846 := dm_build_842.dm_build_737(dm_build_845)
+	if dm_build_846 != nil {
+		return dm_build_846
+	}
+
+	return nil
+}
+
+func (dm_build_848 *dm_build_697) Dm_build_847(dm_build_849 []uint32) ([]int64, error) {
+	dm_build_850 := dm_build_1598(dm_build_848, dm_build_849)
+	dm_build_851, dm_build_852 := dm_build_848.dm_build_737(dm_build_850)
+	if dm_build_852 != nil {
+		return nil, dm_build_852
+	}
+	return dm_build_851.([]int64), nil
+}
+
+func (dm_build_854 *dm_build_697) Close() error {
+	if dm_build_854.dm_build_708 {
+		return nil
+	}
+
+	dm_build_855 := dm_build_854.dm_build_698.Close()
+	if dm_build_855 != nil {
+		return dm_build_855
+	}
+
+	dm_build_854.dm_build_701 = nil
+	dm_build_854.dm_build_708 = true
+	return nil
+}
+
+func (dm_build_857 *dm_build_697) dm_build_856(dm_build_858 *lob) (int64, error) {
+	dm_build_859 := dm_build_1369(dm_build_857, dm_build_858)
+	dm_build_860, dm_build_861 := dm_build_857.dm_build_737(dm_build_859)
+	if dm_build_861 != nil {
+		return 0, dm_build_861
+	}
+	return dm_build_860.(int64), nil
+}
+
+func (dm_build_863 *dm_build_697) dm_build_862(dm_build_864 *lob, dm_build_865 int32, dm_build_866 int32) ([]byte, error) {
+	dm_build_867 := dm_build_1356(dm_build_863, dm_build_864, int(dm_build_865), int(dm_build_866))
+	dm_build_868, dm_build_869 := dm_build_863.dm_build_737(dm_build_867)
+	if dm_build_869 != nil {
+		return nil, dm_build_869
+	}
+	return dm_build_868.([]byte), nil
+}
+
+func (dm_build_871 *dm_build_697) dm_build_870(dm_build_872 *DmBlob, dm_build_873 int32, dm_build_874 int32) ([]byte, error) {
+	var dm_build_875 = make([]byte, dm_build_874)
+	var dm_build_876 int32 = 0
+	var dm_build_877 int32 = 0
+	var dm_build_878 []byte
+	var dm_build_879 error
+	for dm_build_876 < dm_build_874 {
+		dm_build_877 = dm_build_874 - dm_build_876
+		if dm_build_877 > Dm_build_1090 {
+			dm_build_877 = Dm_build_1090
+		}
+		dm_build_878, dm_build_879 = dm_build_871.dm_build_862(&dm_build_872.lob, dm_build_873, dm_build_877)
+		if dm_build_879 != nil {
+			return nil, dm_build_879
+		}
+		if dm_build_878 == nil || len(dm_build_878) == 0 {
+			break
+		}
+		Dm_build_1.Dm_build_57(dm_build_875, int(dm_build_876), dm_build_878, 0, len(dm_build_878))
+		dm_build_876 += int32(len(dm_build_878))
+		dm_build_873 += int32(len(dm_build_878))
+		if dm_build_872.readOver {
+			break
+		}
+	}
+	return dm_build_875, nil
+}
+
+func (dm_build_881 *dm_build_697) dm_build_880(dm_build_882 *DmClob, dm_build_883 int32, dm_build_884 int32) (string, error) {
+	var dm_build_885 bytes.Buffer
+	var dm_build_886 int32 = 0
+	var dm_build_887 int32 = 0
+	var dm_build_888 []byte
+	var dm_build_889 string
+	var dm_build_890 error
+	for dm_build_886 < dm_build_884 {
+		dm_build_887 = dm_build_884 - dm_build_886
+		if dm_build_887 > Dm_build_1090/2 {
+			dm_build_887 = Dm_build_1090 / 2
+		}
+		dm_build_888, dm_build_890 = dm_build_881.dm_build_862(&dm_build_882.lob, dm_build_883, dm_build_887)
+		if dm_build_890 != nil {
+			return "", dm_build_890
+		}
+		if dm_build_888 == nil || len(dm_build_888) == 0 {
+			break
+		}
+		dm_build_889 = Dm_build_1.Dm_build_158(dm_build_888, 0, len(dm_build_888), dm_build_882.serverEncoding, dm_build_881.dm_build_701)
+
+		dm_build_885.WriteString(dm_build_889)
+		strLen := utf8.RuneCountInString(dm_build_889)
+		dm_build_886 += int32(strLen)
+		dm_build_883 += int32(strLen)
+		if dm_build_882.readOver {
+			break
+		}
+	}
+	return dm_build_885.String(), nil
+}
+
+func (dm_build_892 *dm_build_697) dm_build_891(dm_build_893 *DmClob, dm_build_894 int, dm_build_895 string, dm_build_896 string) (int, error) {
+	var dm_build_897 = Dm_build_1.Dm_build_217(dm_build_895, dm_build_896, dm_build_892.dm_build_701)
+	var dm_build_898 = 0
+	var dm_build_899 = len(dm_build_897)
+	var dm_build_900 = 0
+	var dm_build_901 = 0
+	var dm_build_902 = 0
+	var dm_build_903 = dm_build_899/Dm_build_1089 + 1
+	var dm_build_904 byte = 0
+	var dm_build_905 byte = 0x01
+	var dm_build_906 byte = 0x02
+	for i := 0; i < dm_build_903; i++ {
+		dm_build_904 = 0
+		if i == 0 {
+			dm_build_904 |= dm_build_905
+		}
+		if i == dm_build_903-1 {
+			dm_build_904 |= dm_build_906
+		}
+		dm_build_902 = dm_build_899 - dm_build_901
+		if dm_build_902 > Dm_build_1089 {
+			dm_build_902 = Dm_build_1089
+		}
+
+		setLobData := dm_build_1514(dm_build_892, &dm_build_893.lob, dm_build_904, dm_build_894, dm_build_897, dm_build_898, dm_build_902)
+		ret, err := dm_build_892.dm_build_737(setLobData)
+		if err != nil {
+			return 0, err
+		}
+		tmp := ret.(int32)
+		if err != nil {
+			return -1, err
+		}
+		if tmp <= 0 {
+			return dm_build_900, nil
+		} else {
+			dm_build_894 += int(tmp)
+			dm_build_900 += int(tmp)
+			dm_build_901 += dm_build_902
+			dm_build_898 += dm_build_902
+		}
+	}
+	return dm_build_900, nil
+}
+
+func (dm_build_908 *dm_build_697) dm_build_907(dm_build_909 *DmBlob, dm_build_910 int, dm_build_911 []byte) (int, error) {
+	var dm_build_912 = 0
+	var dm_build_913 = len(dm_build_911)
+	var dm_build_914 = 0
+	var dm_build_915 = 0
+	var dm_build_916 = 0
+	var dm_build_917 = dm_build_913/Dm_build_1089 + 1
+	var dm_build_918 byte = 0
+	var dm_build_919 byte = 0x01
+	var dm_build_920 byte = 0x02
+	for i := 0; i < dm_build_917; i++ {
+		dm_build_918 = 0
+		if i == 0 {
+			dm_build_918 |= dm_build_919
+		}
+		if i == dm_build_917-1 {
+			dm_build_918 |= dm_build_920
+		}
+		dm_build_916 = dm_build_913 - dm_build_915
+		if dm_build_916 > Dm_build_1089 {
+			dm_build_916 = Dm_build_1089
+		}
+
+		setLobData := dm_build_1514(dm_build_908, &dm_build_909.lob, dm_build_918, dm_build_910, dm_build_911, dm_build_912, dm_build_916)
+		ret, err := dm_build_908.dm_build_737(setLobData)
+		if err != nil {
+			return 0, err
+		}
+		tmp := ret.(int32)
+		if tmp <= 0 {
+			return dm_build_914, nil
+		} else {
+			dm_build_910 += int(tmp)
+			dm_build_914 += int(tmp)
+			dm_build_915 += dm_build_916
+			dm_build_912 += dm_build_916
+		}
+	}
+	return dm_build_914, nil
+}
+
+func (dm_build_922 *dm_build_697) dm_build_921(dm_build_923 *lob, dm_build_924 int) (int64, error) {
+	dm_build_925 := dm_build_1380(dm_build_922, dm_build_923, dm_build_924)
+	dm_build_926, dm_build_927 := dm_build_922.dm_build_737(dm_build_925)
+	if dm_build_927 != nil {
+		return dm_build_923.length, dm_build_927
+	}
+	return dm_build_926.(int64), nil
+}
+
+func (dm_build_929 *dm_build_697) dm_build_928(dm_build_930 []interface{}, dm_build_931 []interface{}, dm_build_932 int) bool {
+	var dm_build_933 = false
+	dm_build_930[dm_build_932] = dm_build_931[dm_build_932]
+
+	if binder, ok := dm_build_931[dm_build_932].(iOffRowBinder); ok {
+		dm_build_933 = true
+		dm_build_930[dm_build_932] = make([]byte, 0)
+		var lob lob
+		if l, ok := binder.getObj().(DmBlob); ok {
+			lob = l.lob
+		} else if l, ok := binder.getObj().(DmClob); ok {
+			lob = l.lob
+		}
+		if &lob != nil && lob.canOptimized(dm_build_929.dm_build_701) {
+			dm_build_930[dm_build_932] = &lobCtl{lob.buildCtlData()}
+			dm_build_933 = false
+		}
+	} else {
+		dm_build_930[dm_build_932] = dm_build_931[dm_build_932]
+	}
+	return dm_build_933
+}
+
+func (dm_build_935 *dm_build_697) dm_build_934(dm_build_936 *DmStatement, dm_build_937 parameter, dm_build_938 int, dm_build_939 iOffRowBinder) error {
+	var dm_build_940 = Dm_build_287()
+	dm_build_939.read(dm_build_940)
+	var dm_build_941 = 0
+	for !dm_build_939.isReadOver() || dm_build_940.Dm_build_288() > 0 {
+		if !dm_build_939.isReadOver() && dm_build_940.Dm_build_288() < Dm_build_1089 {
+			dm_build_939.read(dm_build_940)
+		}
+		if dm_build_940.Dm_build_288() > Dm_build_1089 {
+			dm_build_941 = Dm_build_1089
+		} else {
+			dm_build_941 = dm_build_940.Dm_build_288()
+		}
+
+		putData := dm_build_1485(dm_build_935, dm_build_936, int16(dm_build_938), dm_build_940, int32(dm_build_941))
+		_, err := dm_build_935.dm_build_737(putData)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func (dm_build_943 *dm_build_697) dm_build_942() ([]byte, error) {
+	var dm_build_944 error
+	if dm_build_943.dm_build_705 == nil {
+		if dm_build_943.dm_build_705, dm_build_944 = security.NewClientKeyPair(); dm_build_944 != nil {
+			return nil, dm_build_944
+		}
+	}
+	return security.Bn2Bytes(dm_build_943.dm_build_705.GetY(), security.DH_KEY_LENGTH), nil
+}
+
+func (dm_build_946 *dm_build_697) dm_build_945() (*security.DhKey, error) {
+	var dm_build_947 error
+	if dm_build_946.dm_build_705 == nil {
+		if dm_build_946.dm_build_705, dm_build_947 = security.NewClientKeyPair(); dm_build_947 != nil {
+			return nil, dm_build_947
+		}
+	}
+	return dm_build_946.dm_build_705, nil
+}
+
+func (dm_build_949 *dm_build_697) dm_build_948(dm_build_950 int, dm_build_951 []byte, dm_build_952 string, dm_build_953 int) (dm_build_954 error) {
+	if dm_build_950 > 0 && dm_build_950 < security.MIN_EXTERNAL_CIPHER_ID && dm_build_951 != nil {
+		dm_build_949.dm_build_702, dm_build_954 = security.NewSymmCipher(dm_build_950, dm_build_951)
+	} else if dm_build_950 >= security.MIN_EXTERNAL_CIPHER_ID {
+		if dm_build_949.dm_build_702, dm_build_954 = security.NewThirdPartCipher(dm_build_950, dm_build_951, dm_build_952, dm_build_953); dm_build_954 != nil {
+			dm_build_954 = THIRD_PART_CIPHER_INIT_FAILED.addDetailln(dm_build_954.Error()).throw()
+		}
+	}
+	return
+}
+
+func (dm_build_956 *dm_build_697) dm_build_955(dm_build_957 bool) (dm_build_958 error) {
+	if dm_build_956.dm_build_699, dm_build_958 = security.NewTLSFromTCP(dm_build_956.dm_build_698, dm_build_956.dm_build_701.dmConnector.sslCertPath, dm_build_956.dm_build_701.dmConnector.sslKeyPath, dm_build_956.dm_build_701.dmConnector.user); dm_build_958 != nil {
+		return
+	}
+	if !dm_build_957 {
+		dm_build_956.dm_build_699 = nil
+	}
+	return
+}
+
+func (dm_build_960 *dm_build_697) dm_build_959(dm_build_961 dm_build_1097) bool {
+	return dm_build_961.dm_build_1112() != Dm_build_1004 && dm_build_960.dm_build_701.sslEncrypt == 1
+}

+ 45 - 0
b.go

@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package dm
+
+type ArrayDescriptor struct {
+	m_typeDesc *TypeDescriptor
+}
+
+func newArrayDescriptor(fulName string, conn *DmConnection) (*ArrayDescriptor, error) {
+
+	ad := new(ArrayDescriptor)
+
+	if fulName == "" {
+		return nil, ECGO_INVALID_COMPLEX_TYPE_NAME.throw()
+	}
+
+	ad.m_typeDesc = newTypeDescriptorWithFulName(fulName, conn)
+	err := ad.m_typeDesc.parseDescByName()
+	if err != nil {
+		return nil, err
+	}
+
+	return ad, nil
+}
+
+func newArrayDescriptorByTypeDescriptor(desc *TypeDescriptor) *ArrayDescriptor {
+	ad := new(ArrayDescriptor)
+	ad.m_typeDesc = desc
+	return ad
+}
+
+func (ad *ArrayDescriptor) getMDesc() *TypeDescriptor {
+	return ad.m_typeDesc
+}
+
+func (ad *ArrayDescriptor) getItemDesc() *TypeDescriptor {
+	return ad.m_typeDesc.m_arrObj
+}
+
+func (ad *ArrayDescriptor) getLength() int {
+	return ad.m_typeDesc.m_length
+}

+ 495 - 0
c.go

@@ -0,0 +1,495 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"io"
+	"math"
+)
+
+type Dm_build_361 struct {
+	dm_build_362 []byte
+	dm_build_363 int
+}
+
+func Dm_build_364(dm_build_365 int) *Dm_build_361 {
+	return &Dm_build_361{make([]byte, 0, dm_build_365), 0}
+}
+
+func Dm_build_366(dm_build_367 []byte) *Dm_build_361 {
+	return &Dm_build_361{dm_build_367, 0}
+}
+
+func (dm_build_369 *Dm_build_361) dm_build_368(dm_build_370 int) *Dm_build_361 {
+
+	dm_build_371 := len(dm_build_369.dm_build_362)
+	dm_build_372 := cap(dm_build_369.dm_build_362)
+
+	if dm_build_371+dm_build_370 <= dm_build_372 {
+		dm_build_369.dm_build_362 = dm_build_369.dm_build_362[:dm_build_371+dm_build_370]
+	} else {
+
+		var calCap = int64(math.Max(float64(2*dm_build_372), float64(dm_build_370+dm_build_371)))
+
+		nbuf := make([]byte, dm_build_370+dm_build_371, calCap)
+		copy(nbuf, dm_build_369.dm_build_362)
+		dm_build_369.dm_build_362 = nbuf
+	}
+
+	return dm_build_369
+}
+
+func (dm_build_374 *Dm_build_361) Dm_build_373() int {
+	return len(dm_build_374.dm_build_362)
+}
+
+func (dm_build_376 *Dm_build_361) Dm_build_375(dm_build_377 int) *Dm_build_361 {
+	for i := dm_build_377; i < len(dm_build_376.dm_build_362); i++ {
+		dm_build_376.dm_build_362[i] = 0
+	}
+	dm_build_376.dm_build_362 = dm_build_376.dm_build_362[:dm_build_377]
+	return dm_build_376
+}
+
+func (dm_build_379 *Dm_build_361) Dm_build_378(dm_build_380 int) *Dm_build_361 {
+	dm_build_379.dm_build_363 = dm_build_380
+	return dm_build_379
+}
+
+func (dm_build_382 *Dm_build_361) Dm_build_381() int {
+	return dm_build_382.dm_build_363
+}
+
+func (dm_build_384 *Dm_build_361) Dm_build_383(dm_build_385 bool) int {
+	return len(dm_build_384.dm_build_362) - dm_build_384.dm_build_363
+}
+
+func (dm_build_387 *Dm_build_361) Dm_build_386(dm_build_388 int, dm_build_389 bool, dm_build_390 bool) *Dm_build_361 {
+
+	if dm_build_389 {
+		if dm_build_390 {
+			dm_build_387.dm_build_368(dm_build_388)
+		} else {
+			dm_build_387.dm_build_362 = dm_build_387.dm_build_362[:len(dm_build_387.dm_build_362)-dm_build_388]
+		}
+	} else {
+		if dm_build_390 {
+			dm_build_387.dm_build_363 += dm_build_388
+		} else {
+			dm_build_387.dm_build_363 -= dm_build_388
+		}
+	}
+
+	return dm_build_387
+}
+
+func (dm_build_392 *Dm_build_361) Dm_build_391(dm_build_393 io.Reader, dm_build_394 int) (int, error) {
+	dm_build_395 := len(dm_build_392.dm_build_362)
+	dm_build_392.dm_build_368(dm_build_394)
+	dm_build_396 := 0
+	for dm_build_394 > 0 {
+		n, err := dm_build_393.Read(dm_build_392.dm_build_362[dm_build_395+dm_build_396:])
+		if n > 0 && err == io.EOF {
+			dm_build_396 += n
+			dm_build_392.dm_build_362 = dm_build_392.dm_build_362[:dm_build_395+dm_build_396]
+			return dm_build_396, nil
+		} else if n > 0 && err == nil {
+			dm_build_394 -= n
+			dm_build_396 += n
+		} else if n == 0 && err != nil {
+			return -1, ECGO_COMMUNITION_ERROR.addDetailln(err.Error()).throw()
+		}
+	}
+
+	return dm_build_396, nil
+}
+
+func (dm_build_398 *Dm_build_361) Dm_build_397(dm_build_399 io.Writer) (*Dm_build_361, error) {
+	if _, err := dm_build_399.Write(dm_build_398.dm_build_362); err != nil {
+		return nil, ECGO_COMMUNITION_ERROR.addDetailln(err.Error()).throw()
+	}
+	return dm_build_398, nil
+}
+
+func (dm_build_401 *Dm_build_361) Dm_build_400(dm_build_402 bool) int {
+	dm_build_403 := len(dm_build_401.dm_build_362)
+	dm_build_401.dm_build_368(1)
+
+	if dm_build_402 {
+		return copy(dm_build_401.dm_build_362[dm_build_403:], []byte{1})
+	} else {
+		return copy(dm_build_401.dm_build_362[dm_build_403:], []byte{0})
+	}
+}
+
+func (dm_build_405 *Dm_build_361) Dm_build_404(dm_build_406 byte) int {
+	dm_build_407 := len(dm_build_405.dm_build_362)
+	dm_build_405.dm_build_368(1)
+
+	return copy(dm_build_405.dm_build_362[dm_build_407:], Dm_build_1.Dm_build_179(dm_build_406))
+}
+
+func (dm_build_409 *Dm_build_361) Dm_build_408(dm_build_410 int8) int {
+	dm_build_411 := len(dm_build_409.dm_build_362)
+	dm_build_409.dm_build_368(1)
+
+	return copy(dm_build_409.dm_build_362[dm_build_411:], Dm_build_1.Dm_build_182(dm_build_410))
+}
+
+func (dm_build_413 *Dm_build_361) Dm_build_412(dm_build_414 int16) int {
+	dm_build_415 := len(dm_build_413.dm_build_362)
+	dm_build_413.dm_build_368(2)
+
+	return copy(dm_build_413.dm_build_362[dm_build_415:], Dm_build_1.Dm_build_185(dm_build_414))
+}
+
+func (dm_build_417 *Dm_build_361) Dm_build_416(dm_build_418 int32) int {
+	dm_build_419 := len(dm_build_417.dm_build_362)
+	dm_build_417.dm_build_368(4)
+
+	return copy(dm_build_417.dm_build_362[dm_build_419:], Dm_build_1.Dm_build_188(dm_build_418))
+}
+
+func (dm_build_421 *Dm_build_361) Dm_build_420(dm_build_422 uint8) int {
+	dm_build_423 := len(dm_build_421.dm_build_362)
+	dm_build_421.dm_build_368(1)
+
+	return copy(dm_build_421.dm_build_362[dm_build_423:], Dm_build_1.Dm_build_200(dm_build_422))
+}
+
+func (dm_build_425 *Dm_build_361) Dm_build_424(dm_build_426 uint16) int {
+	dm_build_427 := len(dm_build_425.dm_build_362)
+	dm_build_425.dm_build_368(2)
+
+	return copy(dm_build_425.dm_build_362[dm_build_427:], Dm_build_1.Dm_build_203(dm_build_426))
+}
+
+func (dm_build_429 *Dm_build_361) Dm_build_428(dm_build_430 uint32) int {
+	dm_build_431 := len(dm_build_429.dm_build_362)
+	dm_build_429.dm_build_368(4)
+
+	return copy(dm_build_429.dm_build_362[dm_build_431:], Dm_build_1.Dm_build_206(dm_build_430))
+}
+
+func (dm_build_433 *Dm_build_361) Dm_build_432(dm_build_434 uint64) int {
+	dm_build_435 := len(dm_build_433.dm_build_362)
+	dm_build_433.dm_build_368(8)
+
+	return copy(dm_build_433.dm_build_362[dm_build_435:], Dm_build_1.Dm_build_209(dm_build_434))
+}
+
+func (dm_build_437 *Dm_build_361) Dm_build_436(dm_build_438 float32) int {
+	dm_build_439 := len(dm_build_437.dm_build_362)
+	dm_build_437.dm_build_368(4)
+
+	return copy(dm_build_437.dm_build_362[dm_build_439:], Dm_build_1.Dm_build_206(math.Float32bits(dm_build_438)))
+}
+
+func (dm_build_441 *Dm_build_361) Dm_build_440(dm_build_442 float64) int {
+	dm_build_443 := len(dm_build_441.dm_build_362)
+	dm_build_441.dm_build_368(8)
+
+	return copy(dm_build_441.dm_build_362[dm_build_443:], Dm_build_1.Dm_build_209(math.Float64bits(dm_build_442)))
+}
+
+func (dm_build_445 *Dm_build_361) Dm_build_444(dm_build_446 []byte) int {
+	dm_build_447 := len(dm_build_445.dm_build_362)
+	dm_build_445.dm_build_368(len(dm_build_446))
+	return copy(dm_build_445.dm_build_362[dm_build_447:], dm_build_446)
+}
+
+func (dm_build_449 *Dm_build_361) Dm_build_448(dm_build_450 []byte) int {
+	return dm_build_449.Dm_build_416(int32(len(dm_build_450))) + dm_build_449.Dm_build_444(dm_build_450)
+}
+
+func (dm_build_452 *Dm_build_361) Dm_build_451(dm_build_453 []byte) int {
+	return dm_build_452.Dm_build_420(uint8(len(dm_build_453))) + dm_build_452.Dm_build_444(dm_build_453)
+}
+
+func (dm_build_455 *Dm_build_361) Dm_build_454(dm_build_456 []byte) int {
+	return dm_build_455.Dm_build_424(uint16(len(dm_build_456))) + dm_build_455.Dm_build_444(dm_build_456)
+}
+
+func (dm_build_458 *Dm_build_361) Dm_build_457(dm_build_459 []byte) int {
+	return dm_build_458.Dm_build_444(dm_build_459) + dm_build_458.Dm_build_404(0)
+}
+
+func (dm_build_461 *Dm_build_361) Dm_build_460(dm_build_462 string, dm_build_463 string, dm_build_464 *DmConnection) int {
+	dm_build_465 := Dm_build_1.Dm_build_217(dm_build_462, dm_build_463, dm_build_464)
+	return dm_build_461.Dm_build_448(dm_build_465)
+}
+
+func (dm_build_467 *Dm_build_361) Dm_build_466(dm_build_468 string, dm_build_469 string, dm_build_470 *DmConnection) int {
+	dm_build_471 := Dm_build_1.Dm_build_217(dm_build_468, dm_build_469, dm_build_470)
+	return dm_build_467.Dm_build_451(dm_build_471)
+}
+
+func (dm_build_473 *Dm_build_361) Dm_build_472(dm_build_474 string, dm_build_475 string, dm_build_476 *DmConnection) int {
+	dm_build_477 := Dm_build_1.Dm_build_217(dm_build_474, dm_build_475, dm_build_476)
+	return dm_build_473.Dm_build_454(dm_build_477)
+}
+
+func (dm_build_479 *Dm_build_361) Dm_build_478(dm_build_480 string, dm_build_481 string, dm_build_482 *DmConnection) int {
+	dm_build_483 := Dm_build_1.Dm_build_217(dm_build_480, dm_build_481, dm_build_482)
+	return dm_build_479.Dm_build_457(dm_build_483)
+}
+
+func (dm_build_485 *Dm_build_361) Dm_build_484() byte {
+	dm_build_486 := Dm_build_1.Dm_build_94(dm_build_485.dm_build_362, dm_build_485.dm_build_363)
+	dm_build_485.dm_build_363++
+	return dm_build_486
+}
+
+func (dm_build_488 *Dm_build_361) Dm_build_487() int16 {
+	dm_build_489 := Dm_build_1.Dm_build_98(dm_build_488.dm_build_362, dm_build_488.dm_build_363)
+	dm_build_488.dm_build_363 += 2
+	return dm_build_489
+}
+
+func (dm_build_491 *Dm_build_361) Dm_build_490() int32 {
+	dm_build_492 := Dm_build_1.Dm_build_103(dm_build_491.dm_build_362, dm_build_491.dm_build_363)
+	dm_build_491.dm_build_363 += 4
+	return dm_build_492
+}
+
+func (dm_build_494 *Dm_build_361) Dm_build_493() int64 {
+	dm_build_495 := Dm_build_1.Dm_build_108(dm_build_494.dm_build_362, dm_build_494.dm_build_363)
+	dm_build_494.dm_build_363 += 8
+	return dm_build_495
+}
+
+func (dm_build_497 *Dm_build_361) Dm_build_496() float32 {
+	dm_build_498 := Dm_build_1.Dm_build_113(dm_build_497.dm_build_362, dm_build_497.dm_build_363)
+	dm_build_497.dm_build_363 += 4
+	return dm_build_498
+}
+
+func (dm_build_500 *Dm_build_361) Dm_build_499() float64 {
+	dm_build_501 := Dm_build_1.Dm_build_117(dm_build_500.dm_build_362, dm_build_500.dm_build_363)
+	dm_build_500.dm_build_363 += 8
+	return dm_build_501
+}
+
+func (dm_build_503 *Dm_build_361) Dm_build_502() uint8 {
+	dm_build_504 := Dm_build_1.Dm_build_121(dm_build_503.dm_build_362, dm_build_503.dm_build_363)
+	dm_build_503.dm_build_363 += 1
+	return dm_build_504
+}
+
+func (dm_build_506 *Dm_build_361) Dm_build_505() uint16 {
+	dm_build_507 := Dm_build_1.Dm_build_125(dm_build_506.dm_build_362, dm_build_506.dm_build_363)
+	dm_build_506.dm_build_363 += 2
+	return dm_build_507
+}
+
+func (dm_build_509 *Dm_build_361) Dm_build_508() uint32 {
+	dm_build_510 := Dm_build_1.Dm_build_130(dm_build_509.dm_build_362, dm_build_509.dm_build_363)
+	dm_build_509.dm_build_363 += 4
+	return dm_build_510
+}
+
+func (dm_build_512 *Dm_build_361) Dm_build_511(dm_build_513 int) []byte {
+	dm_build_514 := Dm_build_1.Dm_build_152(dm_build_512.dm_build_362, dm_build_512.dm_build_363, dm_build_513)
+	dm_build_512.dm_build_363 += dm_build_513
+	return dm_build_514
+}
+
+func (dm_build_516 *Dm_build_361) Dm_build_515() []byte {
+	return dm_build_516.Dm_build_511(int(dm_build_516.Dm_build_490()))
+}
+
+func (dm_build_518 *Dm_build_361) Dm_build_517() []byte {
+	return dm_build_518.Dm_build_511(int(dm_build_518.Dm_build_484()))
+}
+
+func (dm_build_520 *Dm_build_361) Dm_build_519() []byte {
+	return dm_build_520.Dm_build_511(int(dm_build_520.Dm_build_487()))
+}
+
+func (dm_build_522 *Dm_build_361) Dm_build_521(dm_build_523 int) []byte {
+	return dm_build_522.Dm_build_511(dm_build_523)
+}
+
+func (dm_build_525 *Dm_build_361) Dm_build_524() []byte {
+	dm_build_526 := 0
+	for dm_build_525.Dm_build_484() != 0 {
+		dm_build_526++
+	}
+	dm_build_525.Dm_build_386(dm_build_526, false, false)
+	return dm_build_525.Dm_build_511(dm_build_526)
+}
+
+func (dm_build_528 *Dm_build_361) Dm_build_527(dm_build_529 int, dm_build_530 string, dm_build_531 *DmConnection) string {
+	return Dm_build_1.Dm_build_254(dm_build_528.Dm_build_511(dm_build_529), dm_build_530, dm_build_531)
+}
+
+func (dm_build_533 *Dm_build_361) Dm_build_532(dm_build_534 string, dm_build_535 *DmConnection) string {
+	return Dm_build_1.Dm_build_254(dm_build_533.Dm_build_515(), dm_build_534, dm_build_535)
+}
+
+func (dm_build_537 *Dm_build_361) Dm_build_536(dm_build_538 string, dm_build_539 *DmConnection) string {
+	return Dm_build_1.Dm_build_254(dm_build_537.Dm_build_517(), dm_build_538, dm_build_539)
+}
+
+func (dm_build_541 *Dm_build_361) Dm_build_540(dm_build_542 string, dm_build_543 *DmConnection) string {
+	return Dm_build_1.Dm_build_254(dm_build_541.Dm_build_519(), dm_build_542, dm_build_543)
+}
+
+func (dm_build_545 *Dm_build_361) Dm_build_544(dm_build_546 string, dm_build_547 *DmConnection) string {
+	return Dm_build_1.Dm_build_254(dm_build_545.Dm_build_524(), dm_build_546, dm_build_547)
+}
+
+func (dm_build_549 *Dm_build_361) Dm_build_548(dm_build_550 int, dm_build_551 byte) int {
+	return dm_build_549.Dm_build_584(dm_build_550, Dm_build_1.Dm_build_179(dm_build_551))
+}
+
+func (dm_build_553 *Dm_build_361) Dm_build_552(dm_build_554 int, dm_build_555 int16) int {
+	return dm_build_553.Dm_build_584(dm_build_554, Dm_build_1.Dm_build_185(dm_build_555))
+}
+
+func (dm_build_557 *Dm_build_361) Dm_build_556(dm_build_558 int, dm_build_559 int32) int {
+	return dm_build_557.Dm_build_584(dm_build_558, Dm_build_1.Dm_build_188(dm_build_559))
+}
+
+func (dm_build_561 *Dm_build_361) Dm_build_560(dm_build_562 int, dm_build_563 int64) int {
+	return dm_build_561.Dm_build_584(dm_build_562, Dm_build_1.Dm_build_191(dm_build_563))
+}
+
+func (dm_build_565 *Dm_build_361) Dm_build_564(dm_build_566 int, dm_build_567 float32) int {
+	return dm_build_565.Dm_build_584(dm_build_566, Dm_build_1.Dm_build_194(dm_build_567))
+}
+
+func (dm_build_569 *Dm_build_361) Dm_build_568(dm_build_570 int, dm_build_571 float64) int {
+	return dm_build_569.Dm_build_584(dm_build_570, Dm_build_1.Dm_build_197(dm_build_571))
+}
+
+func (dm_build_573 *Dm_build_361) Dm_build_572(dm_build_574 int, dm_build_575 uint8) int {
+	return dm_build_573.Dm_build_584(dm_build_574, Dm_build_1.Dm_build_200(dm_build_575))
+}
+
+func (dm_build_577 *Dm_build_361) Dm_build_576(dm_build_578 int, dm_build_579 uint16) int {
+	return dm_build_577.Dm_build_584(dm_build_578, Dm_build_1.Dm_build_203(dm_build_579))
+}
+
+func (dm_build_581 *Dm_build_361) Dm_build_580(dm_build_582 int, dm_build_583 uint32) int {
+	return dm_build_581.Dm_build_584(dm_build_582, Dm_build_1.Dm_build_206(dm_build_583))
+}
+
+func (dm_build_585 *Dm_build_361) Dm_build_584(dm_build_586 int, dm_build_587 []byte) int {
+	return copy(dm_build_585.dm_build_362[dm_build_586:], dm_build_587)
+}
+
+func (dm_build_589 *Dm_build_361) Dm_build_588(dm_build_590 int, dm_build_591 []byte) int {
+	return dm_build_589.Dm_build_556(dm_build_590, int32(len(dm_build_591))) + dm_build_589.Dm_build_584(dm_build_590+4, dm_build_591)
+}
+
+func (dm_build_593 *Dm_build_361) Dm_build_592(dm_build_594 int, dm_build_595 []byte) int {
+	return dm_build_593.Dm_build_548(dm_build_594, byte(len(dm_build_595))) + dm_build_593.Dm_build_584(dm_build_594+1, dm_build_595)
+}
+
+func (dm_build_597 *Dm_build_361) Dm_build_596(dm_build_598 int, dm_build_599 []byte) int {
+	return dm_build_597.Dm_build_552(dm_build_598, int16(len(dm_build_599))) + dm_build_597.Dm_build_584(dm_build_598+2, dm_build_599)
+}
+
+func (dm_build_601 *Dm_build_361) Dm_build_600(dm_build_602 int, dm_build_603 []byte) int {
+	return dm_build_601.Dm_build_584(dm_build_602, dm_build_603) + dm_build_601.Dm_build_548(dm_build_602+len(dm_build_603), 0)
+}
+
+func (dm_build_605 *Dm_build_361) Dm_build_604(dm_build_606 int, dm_build_607 string, dm_build_608 string, dm_build_609 *DmConnection) int {
+	return dm_build_605.Dm_build_588(dm_build_606, Dm_build_1.Dm_build_217(dm_build_607, dm_build_608, dm_build_609))
+}
+
+func (dm_build_611 *Dm_build_361) Dm_build_610(dm_build_612 int, dm_build_613 string, dm_build_614 string, dm_build_615 *DmConnection) int {
+	return dm_build_611.Dm_build_592(dm_build_612, Dm_build_1.Dm_build_217(dm_build_613, dm_build_614, dm_build_615))
+}
+
+func (dm_build_617 *Dm_build_361) Dm_build_616(dm_build_618 int, dm_build_619 string, dm_build_620 string, dm_build_621 *DmConnection) int {
+	return dm_build_617.Dm_build_596(dm_build_618, Dm_build_1.Dm_build_217(dm_build_619, dm_build_620, dm_build_621))
+}
+
+func (dm_build_623 *Dm_build_361) Dm_build_622(dm_build_624 int, dm_build_625 string, dm_build_626 string, dm_build_627 *DmConnection) int {
+	return dm_build_623.Dm_build_600(dm_build_624, Dm_build_1.Dm_build_217(dm_build_625, dm_build_626, dm_build_627))
+}
+
+func (dm_build_629 *Dm_build_361) Dm_build_628(dm_build_630 int) byte {
+	return Dm_build_1.Dm_build_222(dm_build_629.Dm_build_655(dm_build_630, 1))
+}
+
+func (dm_build_632 *Dm_build_361) Dm_build_631(dm_build_633 int) int16 {
+	return Dm_build_1.Dm_build_225(dm_build_632.Dm_build_655(dm_build_633, 2))
+}
+
+func (dm_build_635 *Dm_build_361) Dm_build_634(dm_build_636 int) int32 {
+	return Dm_build_1.Dm_build_228(dm_build_635.Dm_build_655(dm_build_636, 4))
+}
+
+func (dm_build_638 *Dm_build_361) Dm_build_637(dm_build_639 int) int64 {
+	return Dm_build_1.Dm_build_231(dm_build_638.Dm_build_655(dm_build_639, 8))
+}
+
+func (dm_build_641 *Dm_build_361) Dm_build_640(dm_build_642 int) float32 {
+	return Dm_build_1.Dm_build_234(dm_build_641.Dm_build_655(dm_build_642, 4))
+}
+
+func (dm_build_644 *Dm_build_361) Dm_build_643(dm_build_645 int) float64 {
+	return Dm_build_1.Dm_build_237(dm_build_644.Dm_build_655(dm_build_645, 8))
+}
+
+func (dm_build_647 *Dm_build_361) Dm_build_646(dm_build_648 int) uint8 {
+	return Dm_build_1.Dm_build_240(dm_build_647.Dm_build_655(dm_build_648, 1))
+}
+
+func (dm_build_650 *Dm_build_361) Dm_build_649(dm_build_651 int) uint16 {
+	return Dm_build_1.Dm_build_243(dm_build_650.Dm_build_655(dm_build_651, 2))
+}
+
+func (dm_build_653 *Dm_build_361) Dm_build_652(dm_build_654 int) uint32 {
+	return Dm_build_1.Dm_build_246(dm_build_653.Dm_build_655(dm_build_654, 4))
+}
+
+func (dm_build_656 *Dm_build_361) Dm_build_655(dm_build_657 int, dm_build_658 int) []byte {
+	return dm_build_656.dm_build_362[dm_build_657 : dm_build_657+dm_build_658]
+}
+
+func (dm_build_660 *Dm_build_361) Dm_build_659(dm_build_661 int) []byte {
+	dm_build_662 := dm_build_660.Dm_build_634(dm_build_661)
+	return dm_build_660.Dm_build_655(dm_build_661+4, int(dm_build_662))
+}
+
+func (dm_build_664 *Dm_build_361) Dm_build_663(dm_build_665 int) []byte {
+	dm_build_666 := dm_build_664.Dm_build_628(dm_build_665)
+	return dm_build_664.Dm_build_655(dm_build_665+1, int(dm_build_666))
+}
+
+func (dm_build_668 *Dm_build_361) Dm_build_667(dm_build_669 int) []byte {
+	dm_build_670 := dm_build_668.Dm_build_631(dm_build_669)
+	return dm_build_668.Dm_build_655(dm_build_669+2, int(dm_build_670))
+}
+
+func (dm_build_672 *Dm_build_361) Dm_build_671(dm_build_673 int) []byte {
+	dm_build_674 := 0
+	for dm_build_672.Dm_build_628(dm_build_673) != 0 {
+		dm_build_673++
+		dm_build_674++
+	}
+
+	return dm_build_672.Dm_build_655(dm_build_673-dm_build_674, int(dm_build_674))
+}
+
+func (dm_build_676 *Dm_build_361) Dm_build_675(dm_build_677 int, dm_build_678 string, dm_build_679 *DmConnection) string {
+	return Dm_build_1.Dm_build_254(dm_build_676.Dm_build_659(dm_build_677), dm_build_678, dm_build_679)
+}
+
+func (dm_build_681 *Dm_build_361) Dm_build_680(dm_build_682 int, dm_build_683 string, dm_build_684 *DmConnection) string {
+	return Dm_build_1.Dm_build_254(dm_build_681.Dm_build_663(dm_build_682), dm_build_683, dm_build_684)
+}
+
+func (dm_build_686 *Dm_build_361) Dm_build_685(dm_build_687 int, dm_build_688 string, dm_build_689 *DmConnection) string {
+	return Dm_build_1.Dm_build_254(dm_build_686.Dm_build_667(dm_build_687), dm_build_688, dm_build_689)
+}
+
+func (dm_build_691 *Dm_build_361) Dm_build_690(dm_build_692 int, dm_build_693 string, dm_build_694 *DmConnection) string {
+	return Dm_build_1.Dm_build_254(dm_build_691.Dm_build_671(dm_build_692), dm_build_693, dm_build_694)
+}

+ 206 - 0
d.go

@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"container/list"
+	"io"
+)
+
+type Dm_build_283 struct {
+	dm_build_284 *list.List
+	dm_build_285 *dm_build_337
+	dm_build_286 int
+}
+
+func Dm_build_287() *Dm_build_283 {
+	return &Dm_build_283{
+		dm_build_284: list.New(),
+		dm_build_286: 0,
+	}
+}
+
+func (dm_build_289 *Dm_build_283) Dm_build_288() int {
+	return dm_build_289.dm_build_286
+}
+
+func (dm_build_291 *Dm_build_283) Dm_build_290(dm_build_292 *Dm_build_361, dm_build_293 int) int {
+	var dm_build_294 = 0
+	var dm_build_295 = 0
+	for dm_build_294 < dm_build_293 && dm_build_291.dm_build_285 != nil {
+		dm_build_295 = dm_build_291.dm_build_285.dm_build_345(dm_build_292, dm_build_293-dm_build_294)
+		if dm_build_291.dm_build_285.dm_build_340 == 0 {
+			dm_build_291.dm_build_327()
+		}
+		dm_build_294 += dm_build_295
+		dm_build_291.dm_build_286 -= dm_build_295
+	}
+	return dm_build_294
+}
+
+func (dm_build_297 *Dm_build_283) Dm_build_296(dm_build_298 []byte, dm_build_299 int, dm_build_300 int) int {
+	var dm_build_301 = 0
+	var dm_build_302 = 0
+	for dm_build_301 < dm_build_300 && dm_build_297.dm_build_285 != nil {
+		dm_build_302 = dm_build_297.dm_build_285.dm_build_349(dm_build_298, dm_build_299, dm_build_300-dm_build_301)
+		if dm_build_297.dm_build_285.dm_build_340 == 0 {
+			dm_build_297.dm_build_327()
+		}
+		dm_build_301 += dm_build_302
+		dm_build_297.dm_build_286 -= dm_build_302
+		dm_build_299 += dm_build_302
+	}
+	return dm_build_301
+}
+
+func (dm_build_304 *Dm_build_283) Dm_build_303(dm_build_305 io.Writer, dm_build_306 int) int {
+	var dm_build_307 = 0
+	var dm_build_308 = 0
+	for dm_build_307 < dm_build_306 && dm_build_304.dm_build_285 != nil {
+		dm_build_308 = dm_build_304.dm_build_285.dm_build_354(dm_build_305, dm_build_306-dm_build_307)
+		if dm_build_304.dm_build_285.dm_build_340 == 0 {
+			dm_build_304.dm_build_327()
+		}
+		dm_build_307 += dm_build_308
+		dm_build_304.dm_build_286 -= dm_build_308
+	}
+	return dm_build_307
+}
+
+func (dm_build_310 *Dm_build_283) Dm_build_309(dm_build_311 []byte, dm_build_312 int, dm_build_313 int) {
+	if dm_build_313 == 0 {
+		return
+	}
+	var dm_build_314 = dm_build_341(dm_build_311, dm_build_312, dm_build_313)
+	if dm_build_310.dm_build_285 == nil {
+		dm_build_310.dm_build_285 = dm_build_314
+	} else {
+		dm_build_310.dm_build_284.PushBack(dm_build_314)
+	}
+	dm_build_310.dm_build_286 += dm_build_313
+}
+
+func (dm_build_316 *Dm_build_283) dm_build_315(dm_build_317 int) byte {
+	var dm_build_318 = dm_build_317
+	var dm_build_319 = dm_build_316.dm_build_285
+	for dm_build_318 > 0 && dm_build_319 != nil {
+		if dm_build_319.dm_build_340 == 0 {
+			continue
+		}
+		if dm_build_318 > dm_build_319.dm_build_340-1 {
+			dm_build_318 -= dm_build_319.dm_build_340
+			dm_build_319 = dm_build_316.dm_build_284.Front().Value.(*dm_build_337)
+		} else {
+			break
+		}
+	}
+	return dm_build_319.dm_build_358(dm_build_318)
+}
+func (dm_build_321 *Dm_build_283) Dm_build_320(dm_build_322 *Dm_build_283) {
+	if dm_build_322.dm_build_286 == 0 {
+		return
+	}
+	var dm_build_323 = dm_build_322.dm_build_285
+	for dm_build_323 != nil {
+		dm_build_321.dm_build_324(dm_build_323)
+		dm_build_322.dm_build_327()
+		dm_build_323 = dm_build_322.dm_build_285
+	}
+	dm_build_322.dm_build_286 = 0
+}
+func (dm_build_325 *Dm_build_283) dm_build_324(dm_build_326 *dm_build_337) {
+	if dm_build_326.dm_build_340 == 0 {
+		return
+	}
+	if dm_build_325.dm_build_285 == nil {
+		dm_build_325.dm_build_285 = dm_build_326
+	} else {
+		dm_build_325.dm_build_284.PushBack(dm_build_326)
+	}
+	dm_build_325.dm_build_286 += dm_build_326.dm_build_340
+}
+
+func (dm_build_328 *Dm_build_283) dm_build_327() {
+	var dm_build_329 = dm_build_328.dm_build_284.Front()
+	if dm_build_329 == nil {
+		dm_build_328.dm_build_285 = nil
+	} else {
+		dm_build_328.dm_build_285 = dm_build_329.Value.(*dm_build_337)
+		dm_build_328.dm_build_284.Remove(dm_build_329)
+	}
+}
+
+func (dm_build_331 *Dm_build_283) Dm_build_330() []byte {
+	var dm_build_332 = make([]byte, dm_build_331.dm_build_286)
+	var dm_build_333 = dm_build_331.dm_build_285
+	var dm_build_334 = 0
+	var dm_build_335 = len(dm_build_332)
+	var dm_build_336 = 0
+	for dm_build_333 != nil {
+		if dm_build_333.dm_build_340 > 0 {
+			if dm_build_335 > dm_build_333.dm_build_340 {
+				dm_build_336 = dm_build_333.dm_build_340
+			} else {
+				dm_build_336 = dm_build_335
+			}
+			copy(dm_build_332[dm_build_334:dm_build_334+dm_build_336], dm_build_333.dm_build_338[dm_build_333.dm_build_339:dm_build_333.dm_build_339+dm_build_336])
+			dm_build_334 += dm_build_336
+			dm_build_335 -= dm_build_336
+		}
+		if dm_build_331.dm_build_284.Front() == nil {
+			dm_build_333 = nil
+		} else {
+			dm_build_333 = dm_build_331.dm_build_284.Front().Value.(*dm_build_337)
+		}
+	}
+	return dm_build_332
+}
+
+type dm_build_337 struct {
+	dm_build_338 []byte
+	dm_build_339 int
+	dm_build_340 int
+}
+
+func dm_build_341(dm_build_342 []byte, dm_build_343 int, dm_build_344 int) *dm_build_337 {
+	return &dm_build_337{
+		dm_build_342,
+		dm_build_343,
+		dm_build_344,
+	}
+}
+
+func (dm_build_346 *dm_build_337) dm_build_345(dm_build_347 *Dm_build_361, dm_build_348 int) int {
+	if dm_build_346.dm_build_340 <= dm_build_348 {
+		dm_build_348 = dm_build_346.dm_build_340
+	}
+	dm_build_347.Dm_build_444(dm_build_346.dm_build_338[dm_build_346.dm_build_339 : dm_build_346.dm_build_339+dm_build_348])
+	dm_build_346.dm_build_339 += dm_build_348
+	dm_build_346.dm_build_340 -= dm_build_348
+	return dm_build_348
+}
+
+func (dm_build_350 *dm_build_337) dm_build_349(dm_build_351 []byte, dm_build_352 int, dm_build_353 int) int {
+	if dm_build_350.dm_build_340 <= dm_build_353 {
+		dm_build_353 = dm_build_350.dm_build_340
+	}
+	copy(dm_build_351[dm_build_352:dm_build_352+dm_build_353], dm_build_350.dm_build_338[dm_build_350.dm_build_339:dm_build_350.dm_build_339+dm_build_353])
+	dm_build_350.dm_build_339 += dm_build_353
+	dm_build_350.dm_build_340 -= dm_build_353
+	return dm_build_353
+}
+
+func (dm_build_355 *dm_build_337) dm_build_354(dm_build_356 io.Writer, dm_build_357 int) int {
+	if dm_build_355.dm_build_340 <= dm_build_357 {
+		dm_build_357 = dm_build_355.dm_build_340
+	}
+	dm_build_356.Write(dm_build_355.dm_build_338[dm_build_355.dm_build_339 : dm_build_355.dm_build_339+dm_build_357])
+	dm_build_355.dm_build_339 += dm_build_357
+	dm_build_355.dm_build_340 -= dm_build_357
+	return dm_build_357
+}
+func (dm_build_359 *dm_build_337) dm_build_358(dm_build_360 int) byte {
+	return dm_build_359.dm_build_338[dm_build_359.dm_build_339+dm_build_360]
+}

+ 547 - 0
e.go

@@ -0,0 +1,547 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"bytes"
+	"golang.org/x/text/encoding"
+	"golang.org/x/text/encoding/ianaindex"
+	"golang.org/x/text/transform"
+	"io"
+	"io/ioutil"
+	"math"
+)
+
+type dm_build_0 struct{}
+
+var Dm_build_1 = &dm_build_0{}
+
+func (Dm_build_3 *dm_build_0) Dm_build_2(dm_build_4 []byte, dm_build_5 int, dm_build_6 byte) int {
+	dm_build_4[dm_build_5] = dm_build_6
+	return 1
+}
+
+func (Dm_build_8 *dm_build_0) Dm_build_7(dm_build_9 []byte, dm_build_10 int, dm_build_11 int8) int {
+	dm_build_9[dm_build_10] = byte(dm_build_11)
+	return 1
+}
+
+func (Dm_build_13 *dm_build_0) Dm_build_12(dm_build_14 []byte, dm_build_15 int, dm_build_16 int16) int {
+	dm_build_14[dm_build_15] = byte(dm_build_16)
+	dm_build_15++
+	dm_build_14[dm_build_15] = byte(dm_build_16 >> 8)
+	return 2
+}
+
+func (Dm_build_18 *dm_build_0) Dm_build_17(dm_build_19 []byte, dm_build_20 int, dm_build_21 int32) int {
+	dm_build_19[dm_build_20] = byte(dm_build_21)
+	dm_build_20++
+	dm_build_19[dm_build_20] = byte(dm_build_21 >> 8)
+	dm_build_20++
+	dm_build_19[dm_build_20] = byte(dm_build_21 >> 16)
+	dm_build_20++
+	dm_build_19[dm_build_20] = byte(dm_build_21 >> 24)
+	dm_build_20++
+	return 4
+}
+
+func (Dm_build_23 *dm_build_0) Dm_build_22(dm_build_24 []byte, dm_build_25 int, dm_build_26 int64) int {
+	dm_build_24[dm_build_25] = byte(dm_build_26)
+	dm_build_25++
+	dm_build_24[dm_build_25] = byte(dm_build_26 >> 8)
+	dm_build_25++
+	dm_build_24[dm_build_25] = byte(dm_build_26 >> 16)
+	dm_build_25++
+	dm_build_24[dm_build_25] = byte(dm_build_26 >> 24)
+	dm_build_25++
+	dm_build_24[dm_build_25] = byte(dm_build_26 >> 32)
+	dm_build_25++
+	dm_build_24[dm_build_25] = byte(dm_build_26 >> 40)
+	dm_build_25++
+	dm_build_24[dm_build_25] = byte(dm_build_26 >> 48)
+	dm_build_25++
+	dm_build_24[dm_build_25] = byte(dm_build_26 >> 56)
+	return 8
+}
+
+func (Dm_build_28 *dm_build_0) Dm_build_27(dm_build_29 []byte, dm_build_30 int, dm_build_31 float32) int {
+	return Dm_build_28.Dm_build_47(dm_build_29, dm_build_30, math.Float32bits(dm_build_31))
+}
+
+func (Dm_build_33 *dm_build_0) Dm_build_32(dm_build_34 []byte, dm_build_35 int, dm_build_36 float64) int {
+	return Dm_build_33.Dm_build_52(dm_build_34, dm_build_35, math.Float64bits(dm_build_36))
+}
+
+func (Dm_build_38 *dm_build_0) Dm_build_37(dm_build_39 []byte, dm_build_40 int, dm_build_41 uint8) int {
+	dm_build_39[dm_build_40] = byte(dm_build_41)
+	return 1
+}
+
+func (Dm_build_43 *dm_build_0) Dm_build_42(dm_build_44 []byte, dm_build_45 int, dm_build_46 uint16) int {
+	dm_build_44[dm_build_45] = byte(dm_build_46)
+	dm_build_45++
+	dm_build_44[dm_build_45] = byte(dm_build_46 >> 8)
+	return 2
+}
+
+func (Dm_build_48 *dm_build_0) Dm_build_47(dm_build_49 []byte, dm_build_50 int, dm_build_51 uint32) int {
+	dm_build_49[dm_build_50] = byte(dm_build_51)
+	dm_build_50++
+	dm_build_49[dm_build_50] = byte(dm_build_51 >> 8)
+	dm_build_50++
+	dm_build_49[dm_build_50] = byte(dm_build_51 >> 16)
+	dm_build_50++
+	dm_build_49[dm_build_50] = byte(dm_build_51 >> 24)
+	return 3
+}
+
+func (Dm_build_53 *dm_build_0) Dm_build_52(dm_build_54 []byte, dm_build_55 int, dm_build_56 uint64) int {
+	dm_build_54[dm_build_55] = byte(dm_build_56)
+	dm_build_55++
+	dm_build_54[dm_build_55] = byte(dm_build_56 >> 8)
+	dm_build_55++
+	dm_build_54[dm_build_55] = byte(dm_build_56 >> 16)
+	dm_build_55++
+	dm_build_54[dm_build_55] = byte(dm_build_56 >> 24)
+	dm_build_55++
+	dm_build_54[dm_build_55] = byte(dm_build_56 >> 32)
+	dm_build_55++
+	dm_build_54[dm_build_55] = byte(dm_build_56 >> 40)
+	dm_build_55++
+	dm_build_54[dm_build_55] = byte(dm_build_56 >> 48)
+	dm_build_55++
+	dm_build_54[dm_build_55] = byte(dm_build_56 >> 56)
+	return 3
+}
+
+func (Dm_build_58 *dm_build_0) Dm_build_57(dm_build_59 []byte, dm_build_60 int, dm_build_61 []byte, dm_build_62 int, dm_build_63 int) int {
+	copy(dm_build_59[dm_build_60:dm_build_60+dm_build_63], dm_build_61[dm_build_62:dm_build_62+dm_build_63])
+	return dm_build_63
+}
+
+func (Dm_build_65 *dm_build_0) Dm_build_64(dm_build_66 []byte, dm_build_67 int, dm_build_68 []byte, dm_build_69 int, dm_build_70 int) int {
+	dm_build_67 += Dm_build_65.Dm_build_47(dm_build_66, dm_build_67, uint32(dm_build_70))
+	return 4 + Dm_build_65.Dm_build_57(dm_build_66, dm_build_67, dm_build_68, dm_build_69, dm_build_70)
+}
+
+func (Dm_build_72 *dm_build_0) Dm_build_71(dm_build_73 []byte, dm_build_74 int, dm_build_75 []byte, dm_build_76 int, dm_build_77 int) int {
+	dm_build_74 += Dm_build_72.Dm_build_42(dm_build_73, dm_build_74, uint16(dm_build_77))
+	return 2 + Dm_build_72.Dm_build_57(dm_build_73, dm_build_74, dm_build_75, dm_build_76, dm_build_77)
+}
+
+func (Dm_build_79 *dm_build_0) Dm_build_78(dm_build_80 []byte, dm_build_81 int, dm_build_82 string, dm_build_83 string, dm_build_84 *DmConnection) int {
+	dm_build_85 := Dm_build_79.Dm_build_217(dm_build_82, dm_build_83, dm_build_84)
+	dm_build_81 += Dm_build_79.Dm_build_47(dm_build_80, dm_build_81, uint32(len(dm_build_85)))
+	return 4 + Dm_build_79.Dm_build_57(dm_build_80, dm_build_81, dm_build_85, 0, len(dm_build_85))
+}
+
+func (Dm_build_87 *dm_build_0) Dm_build_86(dm_build_88 []byte, dm_build_89 int, dm_build_90 string, dm_build_91 string, dm_build_92 *DmConnection) int {
+	dm_build_93 := Dm_build_87.Dm_build_217(dm_build_90, dm_build_91, dm_build_92)
+
+	dm_build_89 += Dm_build_87.Dm_build_42(dm_build_88, dm_build_89, uint16(len(dm_build_93)))
+	return 2 + Dm_build_87.Dm_build_57(dm_build_88, dm_build_89, dm_build_93, 0, len(dm_build_93))
+}
+
+func (Dm_build_95 *dm_build_0) Dm_build_94(dm_build_96 []byte, dm_build_97 int) byte {
+	return dm_build_96[dm_build_97]
+}
+
+func (Dm_build_99 *dm_build_0) Dm_build_98(dm_build_100 []byte, dm_build_101 int) int16 {
+	var dm_build_102 int16
+	dm_build_102 = int16(dm_build_100[dm_build_101] & 0xff)
+	dm_build_101++
+	dm_build_102 |= int16(dm_build_100[dm_build_101]&0xff) << 8
+	return dm_build_102
+}
+
+func (Dm_build_104 *dm_build_0) Dm_build_103(dm_build_105 []byte, dm_build_106 int) int32 {
+	var dm_build_107 int32
+	dm_build_107 = int32(dm_build_105[dm_build_106] & 0xff)
+	dm_build_106++
+	dm_build_107 |= int32(dm_build_105[dm_build_106]&0xff) << 8
+	dm_build_106++
+	dm_build_107 |= int32(dm_build_105[dm_build_106]&0xff) << 16
+	dm_build_106++
+	dm_build_107 |= int32(dm_build_105[dm_build_106]&0xff) << 24
+	return dm_build_107
+}
+
+func (Dm_build_109 *dm_build_0) Dm_build_108(dm_build_110 []byte, dm_build_111 int) int64 {
+	var dm_build_112 int64
+	dm_build_112 = int64(dm_build_110[dm_build_111] & 0xff)
+	dm_build_111++
+	dm_build_112 |= int64(dm_build_110[dm_build_111]&0xff) << 8
+	dm_build_111++
+	dm_build_112 |= int64(dm_build_110[dm_build_111]&0xff) << 16
+	dm_build_111++
+	dm_build_112 |= int64(dm_build_110[dm_build_111]&0xff) << 24
+	dm_build_111++
+	dm_build_112 |= int64(dm_build_110[dm_build_111]&0xff) << 32
+	dm_build_111++
+	dm_build_112 |= int64(dm_build_110[dm_build_111]&0xff) << 40
+	dm_build_111++
+	dm_build_112 |= int64(dm_build_110[dm_build_111]&0xff) << 48
+	dm_build_111++
+	dm_build_112 |= int64(dm_build_110[dm_build_111]&0xff) << 56
+	return dm_build_112
+}
+
+func (Dm_build_114 *dm_build_0) Dm_build_113(dm_build_115 []byte, dm_build_116 int) float32 {
+	return math.Float32frombits(Dm_build_114.Dm_build_130(dm_build_115, dm_build_116))
+}
+
+func (Dm_build_118 *dm_build_0) Dm_build_117(dm_build_119 []byte, dm_build_120 int) float64 {
+	return math.Float64frombits(Dm_build_118.Dm_build_135(dm_build_119, dm_build_120))
+}
+
+func (Dm_build_122 *dm_build_0) Dm_build_121(dm_build_123 []byte, dm_build_124 int) uint8 {
+	return uint8(dm_build_123[dm_build_124] & 0xff)
+}
+
+func (Dm_build_126 *dm_build_0) Dm_build_125(dm_build_127 []byte, dm_build_128 int) uint16 {
+	var dm_build_129 uint16
+	dm_build_129 = uint16(dm_build_127[dm_build_128] & 0xff)
+	dm_build_128++
+	dm_build_129 |= uint16(dm_build_127[dm_build_128]&0xff) << 8
+	return dm_build_129
+}
+
+func (Dm_build_131 *dm_build_0) Dm_build_130(dm_build_132 []byte, dm_build_133 int) uint32 {
+	var dm_build_134 uint32
+	dm_build_134 = uint32(dm_build_132[dm_build_133] & 0xff)
+	dm_build_133++
+	dm_build_134 |= uint32(dm_build_132[dm_build_133]&0xff) << 8
+	dm_build_133++
+	dm_build_134 |= uint32(dm_build_132[dm_build_133]&0xff) << 16
+	dm_build_133++
+	dm_build_134 |= uint32(dm_build_132[dm_build_133]&0xff) << 24
+	return dm_build_134
+}
+
+func (Dm_build_136 *dm_build_0) Dm_build_135(dm_build_137 []byte, dm_build_138 int) uint64 {
+	var dm_build_139 uint64
+	dm_build_139 = uint64(dm_build_137[dm_build_138] & 0xff)
+	dm_build_138++
+	dm_build_139 |= uint64(dm_build_137[dm_build_138]&0xff) << 8
+	dm_build_138++
+	dm_build_139 |= uint64(dm_build_137[dm_build_138]&0xff) << 16
+	dm_build_138++
+	dm_build_139 |= uint64(dm_build_137[dm_build_138]&0xff) << 24
+	dm_build_138++
+	dm_build_139 |= uint64(dm_build_137[dm_build_138]&0xff) << 32
+	dm_build_138++
+	dm_build_139 |= uint64(dm_build_137[dm_build_138]&0xff) << 40
+	dm_build_138++
+	dm_build_139 |= uint64(dm_build_137[dm_build_138]&0xff) << 48
+	dm_build_138++
+	dm_build_139 |= uint64(dm_build_137[dm_build_138]&0xff) << 56
+	return dm_build_139
+}
+
+func (Dm_build_141 *dm_build_0) Dm_build_140(dm_build_142 []byte, dm_build_143 int) []byte {
+	dm_build_144 := Dm_build_141.Dm_build_130(dm_build_142, dm_build_143)
+
+	dm_build_145 := make([]byte, dm_build_144)
+	copy(dm_build_145[:int(dm_build_144)], dm_build_142[dm_build_143+4:dm_build_143+4+int(dm_build_144)])
+	return dm_build_145
+}
+
+func (Dm_build_147 *dm_build_0) Dm_build_146(dm_build_148 []byte, dm_build_149 int) []byte {
+	dm_build_150 := Dm_build_147.Dm_build_125(dm_build_148, dm_build_149)
+
+	dm_build_151 := make([]byte, dm_build_150)
+	copy(dm_build_151[:int(dm_build_150)], dm_build_148[dm_build_149+2:dm_build_149+2+int(dm_build_150)])
+	return dm_build_151
+}
+
+func (Dm_build_153 *dm_build_0) Dm_build_152(dm_build_154 []byte, dm_build_155 int, dm_build_156 int) []byte {
+
+	dm_build_157 := make([]byte, dm_build_156)
+	copy(dm_build_157[:dm_build_156], dm_build_154[dm_build_155:dm_build_155+dm_build_156])
+	return dm_build_157
+}
+
+func (Dm_build_159 *dm_build_0) Dm_build_158(dm_build_160 []byte, dm_build_161 int, dm_build_162 int, dm_build_163 string, dm_build_164 *DmConnection) string {
+	return Dm_build_159.Dm_build_254(dm_build_160[dm_build_161:dm_build_161+dm_build_162], dm_build_163, dm_build_164)
+}
+
+func (Dm_build_166 *dm_build_0) Dm_build_165(dm_build_167 []byte, dm_build_168 int, dm_build_169 string, dm_build_170 *DmConnection) string {
+	dm_build_171 := Dm_build_166.Dm_build_130(dm_build_167, dm_build_168)
+	dm_build_168 += 4
+	return Dm_build_166.Dm_build_158(dm_build_167, dm_build_168, int(dm_build_171), dm_build_169, dm_build_170)
+}
+
+func (Dm_build_173 *dm_build_0) Dm_build_172(dm_build_174 []byte, dm_build_175 int, dm_build_176 string, dm_build_177 *DmConnection) string {
+	dm_build_178 := Dm_build_173.Dm_build_125(dm_build_174, dm_build_175)
+	dm_build_175 += 2
+	return Dm_build_173.Dm_build_158(dm_build_174, dm_build_175, int(dm_build_178), dm_build_176, dm_build_177)
+}
+
+func (Dm_build_180 *dm_build_0) Dm_build_179(dm_build_181 byte) []byte {
+	return []byte{dm_build_181}
+}
+
+func (Dm_build_183 *dm_build_0) Dm_build_182(dm_build_184 int8) []byte {
+	return []byte{byte(dm_build_184)}
+}
+
+func (Dm_build_186 *dm_build_0) Dm_build_185(dm_build_187 int16) []byte {
+	return []byte{byte(dm_build_187), byte(dm_build_187 >> 8)}
+}
+
+func (Dm_build_189 *dm_build_0) Dm_build_188(dm_build_190 int32) []byte {
+	return []byte{byte(dm_build_190), byte(dm_build_190 >> 8), byte(dm_build_190 >> 16), byte(dm_build_190 >> 24)}
+}
+
+func (Dm_build_192 *dm_build_0) Dm_build_191(dm_build_193 int64) []byte {
+	return []byte{byte(dm_build_193), byte(dm_build_193 >> 8), byte(dm_build_193 >> 16), byte(dm_build_193 >> 24), byte(dm_build_193 >> 32),
+		byte(dm_build_193 >> 40), byte(dm_build_193 >> 48), byte(dm_build_193 >> 56)}
+}
+
+func (Dm_build_195 *dm_build_0) Dm_build_194(dm_build_196 float32) []byte {
+	return Dm_build_195.Dm_build_206(math.Float32bits(dm_build_196))
+}
+
+func (Dm_build_198 *dm_build_0) Dm_build_197(dm_build_199 float64) []byte {
+	return Dm_build_198.Dm_build_209(math.Float64bits(dm_build_199))
+}
+
+func (Dm_build_201 *dm_build_0) Dm_build_200(dm_build_202 uint8) []byte {
+	return []byte{byte(dm_build_202)}
+}
+
+func (Dm_build_204 *dm_build_0) Dm_build_203(dm_build_205 uint16) []byte {
+	return []byte{byte(dm_build_205), byte(dm_build_205 >> 8)}
+}
+
+func (Dm_build_207 *dm_build_0) Dm_build_206(dm_build_208 uint32) []byte {
+	return []byte{byte(dm_build_208), byte(dm_build_208 >> 8), byte(dm_build_208 >> 16), byte(dm_build_208 >> 24)}
+}
+
+func (Dm_build_210 *dm_build_0) Dm_build_209(dm_build_211 uint64) []byte {
+	return []byte{byte(dm_build_211), byte(dm_build_211 >> 8), byte(dm_build_211 >> 16), byte(dm_build_211 >> 24), byte(dm_build_211 >> 32), byte(dm_build_211 >> 40), byte(dm_build_211 >> 48), byte(dm_build_211 >> 56)}
+}
+
+func (Dm_build_213 *dm_build_0) Dm_build_212(dm_build_214 []byte, dm_build_215 string, dm_build_216 *DmConnection) []byte {
+	if dm_build_215 == "UTF-8" {
+		return dm_build_214
+	}
+
+	if dm_build_216 == nil {
+		if e := dm_build_259(dm_build_215); e != nil {
+			tmp, err := ioutil.ReadAll(
+				transform.NewReader(bytes.NewReader(dm_build_214), e.NewEncoder()),
+			)
+			if err != nil {
+				panic("UTF8 To Charset error!")
+			}
+
+			return tmp
+		}
+
+		panic("Unsupported Charset!")
+	}
+
+	if dm_build_216.encodeBuffer == nil {
+		dm_build_216.encodeBuffer = bytes.NewBuffer(nil)
+		dm_build_216.encode = dm_build_259(dm_build_216.getServerEncoding())
+		dm_build_216.transformReaderDst = make([]byte, 4096)
+		dm_build_216.transformReaderSrc = make([]byte, 4096)
+	}
+
+	if e := dm_build_216.encode; e != nil {
+
+		dm_build_216.encodeBuffer.Reset()
+
+		n, err := dm_build_216.encodeBuffer.ReadFrom(
+			Dm_build_273(bytes.NewReader(dm_build_214), e.NewEncoder(), dm_build_216.transformReaderDst, dm_build_216.transformReaderSrc),
+		)
+		if err != nil {
+			panic("UTF8 To Charset error!")
+		}
+		var tmp = make([]byte, n)
+		if _, err = dm_build_216.encodeBuffer.Read(tmp); err != nil {
+			panic("UTF8 To Charset error!")
+		}
+		return tmp
+	}
+
+	panic("Unsupported Charset!")
+}
+
+func (Dm_build_218 *dm_build_0) Dm_build_217(dm_build_219 string, dm_build_220 string, dm_build_221 *DmConnection) []byte {
+	return Dm_build_218.Dm_build_212([]byte(dm_build_219), dm_build_220, dm_build_221)
+}
+
+func (Dm_build_223 *dm_build_0) Dm_build_222(dm_build_224 []byte) byte {
+	return Dm_build_223.Dm_build_94(dm_build_224, 0)
+}
+
+func (Dm_build_226 *dm_build_0) Dm_build_225(dm_build_227 []byte) int16 {
+	return Dm_build_226.Dm_build_98(dm_build_227, 0)
+}
+
+func (Dm_build_229 *dm_build_0) Dm_build_228(dm_build_230 []byte) int32 {
+	return Dm_build_229.Dm_build_103(dm_build_230, 0)
+}
+
+func (Dm_build_232 *dm_build_0) Dm_build_231(dm_build_233 []byte) int64 {
+	return Dm_build_232.Dm_build_108(dm_build_233, 0)
+}
+
+func (Dm_build_235 *dm_build_0) Dm_build_234(dm_build_236 []byte) float32 {
+	return Dm_build_235.Dm_build_113(dm_build_236, 0)
+}
+
+func (Dm_build_238 *dm_build_0) Dm_build_237(dm_build_239 []byte) float64 {
+	return Dm_build_238.Dm_build_117(dm_build_239, 0)
+}
+
+func (Dm_build_241 *dm_build_0) Dm_build_240(dm_build_242 []byte) uint8 {
+	return Dm_build_241.Dm_build_121(dm_build_242, 0)
+}
+
+func (Dm_build_244 *dm_build_0) Dm_build_243(dm_build_245 []byte) uint16 {
+	return Dm_build_244.Dm_build_125(dm_build_245, 0)
+}
+
+func (Dm_build_247 *dm_build_0) Dm_build_246(dm_build_248 []byte) uint32 {
+	return Dm_build_247.Dm_build_130(dm_build_248, 0)
+}
+
+func (Dm_build_250 *dm_build_0) Dm_build_249(dm_build_251 []byte, dm_build_252 string, dm_build_253 *DmConnection) []byte {
+	if dm_build_252 == "UTF-8" {
+		return dm_build_251
+	}
+
+	if dm_build_253 == nil {
+		if e := dm_build_259(dm_build_252); e != nil {
+
+			tmp, err := ioutil.ReadAll(
+				transform.NewReader(bytes.NewReader(dm_build_251), e.NewDecoder()),
+			)
+			if err != nil {
+
+				panic("Charset To UTF8 error!")
+			}
+
+			return tmp
+		}
+
+		panic("Unsupported Charset!")
+	}
+
+	if dm_build_253.encodeBuffer == nil {
+		dm_build_253.encodeBuffer = bytes.NewBuffer(nil)
+		dm_build_253.encode = dm_build_259(dm_build_253.getServerEncoding())
+		dm_build_253.transformReaderDst = make([]byte, 4096)
+		dm_build_253.transformReaderSrc = make([]byte, 4096)
+	}
+
+	if e := dm_build_253.encode; e != nil {
+
+		dm_build_253.encodeBuffer.Reset()
+
+		n, err := dm_build_253.encodeBuffer.ReadFrom(
+			Dm_build_273(bytes.NewReader(dm_build_251), e.NewDecoder(), dm_build_253.transformReaderDst, dm_build_253.transformReaderSrc),
+		)
+		if err != nil {
+
+			panic("Charset To UTF8 error!")
+		}
+
+		return dm_build_253.encodeBuffer.Next(int(n))
+	}
+
+	panic("Unsupported Charset!")
+}
+
+func (Dm_build_255 *dm_build_0) Dm_build_254(dm_build_256 []byte, dm_build_257 string, dm_build_258 *DmConnection) string {
+	return string(Dm_build_255.Dm_build_249(dm_build_256, dm_build_257, dm_build_258))
+}
+
+func dm_build_259(dm_build_260 string) encoding.Encoding {
+	if e, err := ianaindex.MIB.Encoding(dm_build_260); err == nil && e != nil {
+		return e
+	}
+	return nil
+}
+
+type Dm_build_261 struct {
+	dm_build_262 io.Reader
+	dm_build_263 transform.Transformer
+	dm_build_264 error
+
+	dm_build_265               []byte
+	dm_build_266, dm_build_267 int
+
+	dm_build_268               []byte
+	dm_build_269, dm_build_270 int
+
+	dm_build_271 bool
+}
+
+const dm_build_272 = 4096
+
+func Dm_build_273(dm_build_274 io.Reader, dm_build_275 transform.Transformer, dm_build_276 []byte, dm_build_277 []byte) *Dm_build_261 {
+	dm_build_275.Reset()
+	return &Dm_build_261{
+		dm_build_262: dm_build_274,
+		dm_build_263: dm_build_275,
+		dm_build_265: dm_build_276,
+		dm_build_268: dm_build_277,
+	}
+}
+
+func (dm_build_279 *Dm_build_261) Read(dm_build_280 []byte) (int, error) {
+	dm_build_281, dm_build_282 := 0, error(nil)
+	for {
+
+		if dm_build_279.dm_build_266 != dm_build_279.dm_build_267 {
+			dm_build_281 = copy(dm_build_280, dm_build_279.dm_build_265[dm_build_279.dm_build_266:dm_build_279.dm_build_267])
+			dm_build_279.dm_build_266 += dm_build_281
+			if dm_build_279.dm_build_266 == dm_build_279.dm_build_267 && dm_build_279.dm_build_271 {
+				return dm_build_281, dm_build_279.dm_build_264
+			}
+			return dm_build_281, nil
+		} else if dm_build_279.dm_build_271 {
+			return 0, dm_build_279.dm_build_264
+		}
+
+		if dm_build_279.dm_build_269 != dm_build_279.dm_build_270 || dm_build_279.dm_build_264 != nil {
+			dm_build_279.dm_build_266 = 0
+			dm_build_279.dm_build_267, dm_build_281, dm_build_282 = dm_build_279.dm_build_263.Transform(dm_build_279.dm_build_265, dm_build_279.dm_build_268[dm_build_279.dm_build_269:dm_build_279.dm_build_270], dm_build_279.dm_build_264 == io.EOF)
+			dm_build_279.dm_build_269 += dm_build_281
+
+			switch {
+			case dm_build_282 == nil:
+				if dm_build_279.dm_build_269 != dm_build_279.dm_build_270 {
+					dm_build_279.dm_build_264 = nil
+				}
+
+				dm_build_279.dm_build_271 = dm_build_279.dm_build_264 != nil
+				continue
+			case dm_build_282 == transform.ErrShortDst && (dm_build_279.dm_build_267 != 0 || dm_build_281 != 0):
+
+				continue
+			case dm_build_282 == transform.ErrShortSrc && dm_build_279.dm_build_270-dm_build_279.dm_build_269 != len(dm_build_279.dm_build_268) && dm_build_279.dm_build_264 == nil:
+
+			default:
+				dm_build_279.dm_build_271 = true
+
+				if dm_build_279.dm_build_264 == nil || dm_build_279.dm_build_264 == io.EOF {
+					dm_build_279.dm_build_264 = dm_build_282
+				}
+				continue
+			}
+		}
+
+		if dm_build_279.dm_build_269 != 0 {
+			dm_build_279.dm_build_269, dm_build_279.dm_build_270 = 0, copy(dm_build_279.dm_build_268, dm_build_279.dm_build_268[dm_build_279.dm_build_269:dm_build_279.dm_build_270])
+		}
+		dm_build_281, dm_build_279.dm_build_264 = dm_build_279.dm_build_262.Read(dm_build_279.dm_build_268[dm_build_279.dm_build_270:])
+		dm_build_279.dm_build_270 += dm_build_281
+	}
+}

+ 47 - 0
f.go

@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"bytes"
+	"compress/zlib"
+	"github.com/golang/snappy"
+)
+
+func Compress(srcBuffer *Dm_build_361, offset int, length int, compressID int) ([]byte, error) {
+	if compressID == Dm_build_1055 {
+		return snappy.Encode(nil, srcBuffer.Dm_build_655(offset, length)), nil
+	}
+	return GzlibCompress(srcBuffer, offset, length)
+}
+
+func UnCompress(srcBytes []byte, compressID int) ([]byte, error) {
+	if compressID == Dm_build_1055 {
+		return snappy.Decode(nil, srcBytes)
+	}
+	return GzlibUncompress(srcBytes)
+}
+
+func GzlibCompress(srcBuffer *Dm_build_361, offset int, length int) ([]byte, error) {
+	var ret bytes.Buffer
+	var w = zlib.NewWriter(&ret)
+	w.Write(srcBuffer.Dm_build_655(offset, length))
+	w.Close()
+	return ret.Bytes(), nil
+}
+
+func GzlibUncompress(srcBytes []byte) ([]byte, error) {
+	var bytesBuf = new(bytes.Buffer)
+	r, err := zlib.NewReader(bytes.NewReader(srcBytes))
+	if err != nil {
+		return nil, err
+	}
+	defer r.Close()
+	_, err = bytesBuf.ReadFrom(r)
+	if err != nil {
+		return nil, err
+	}
+	return bytesBuf.Bytes(), nil
+}

+ 2158 - 0
g.go

@@ -0,0 +1,2158 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"fmt"
+	"math"
+	"os"
+	"sort"
+	"strconv"
+	"strings"
+	"sync"
+	"sync/atomic"
+	"time"
+
+	"gitee.com/chunanyong/dm/util"
+)
+
+type ExecuteTypeEnum int
+
+const (
+	Execute ExecuteTypeEnum = iota
+	ExecuteQuery
+	ExecuteUpdate
+)
+
+var idGenerator int64 = 0
+
+func generateId() string {
+	return time.Now().String() + strconv.Itoa(int(atomic.AddInt64(&idGenerator, 1)))
+}
+
+func getInt64(counter *int64, reset bool) int64 {
+	if reset {
+		return atomic.SwapInt64(counter, 0)
+	}
+	return atomic.LoadInt64(counter)
+}
+
+type SqlStatValue struct {
+	id string
+
+	sql string
+
+	sqlHash int64
+
+	dataSource string
+
+	dataSourceId string
+
+	executeLastStartTime int64
+
+	executeBatchSizeTotal int64
+
+	executeBatchSizeMax int64
+
+	executeSuccessCount int64
+
+	executeSpanNanoTotal int64
+
+	executeSpanNanoMax int64
+
+	runningCount int64
+
+	concurrentMax int64
+
+	resultSetHoldTimeNano int64
+
+	executeAndResultSetHoldTime int64
+
+	executeNanoSpanMaxOccurTime int64
+
+	executeErrorCount int64
+
+	executeErrorLast error
+
+	executeErrorLastMessage string
+
+	executeErrorLastStackTrace string
+
+	executeErrorLastTime int64
+
+	updateCount int64
+
+	updateCountMax int64
+
+	fetchRowCount int64
+
+	fetchRowCountMax int64
+
+	inTransactionCount int64
+
+	lastSlowParameters string
+
+	clobOpenCount int64
+
+	blobOpenCount int64
+
+	readStringLength int64
+
+	readBytesLength int64
+
+	inputStreamOpenCount int64
+
+	readerOpenCount int64
+
+	histogram_0_1 int64
+
+	histogram_1_10 int64
+
+	histogram_10_100 int64
+
+	histogram_100_1000 int64
+
+	histogram_1000_10000 int64
+
+	histogram_10000_100000 int64
+
+	histogram_100000_1000000 int64
+
+	histogram_1000000_more int64
+
+	executeAndResultHoldTime_0_1 int64
+
+	executeAndResultHoldTime_1_10 int64
+
+	executeAndResultHoldTime_10_100 int64
+
+	executeAndResultHoldTime_100_1000 int64
+
+	executeAndResultHoldTime_1000_10000 int64
+
+	executeAndResultHoldTime_10000_100000 int64
+
+	executeAndResultHoldTime_100000_1000000 int64
+
+	executeAndResultHoldTime_1000000_more int64
+
+	fetchRowCount_0_1 int64
+
+	fetchRowCount_1_10 int64
+
+	fetchRowCount_10_100 int64
+
+	fetchRowCount_100_1000 int64
+
+	fetchRowCount_1000_10000 int64
+
+	fetchRowCount_10000_more int64
+
+	updateCount_0_1 int64
+
+	updateCount_1_10 int64
+
+	updateCount_10_100 int64
+
+	updateCount_100_1000 int64
+
+	updateCount_1000_10000 int64
+
+	updateCount_10000_more int64
+}
+
+func newSqlStatValue() *SqlStatValue {
+	ssv := new(SqlStatValue)
+	return ssv
+}
+
+func (ssv *SqlStatValue) getExecuteHistogram() []int64 {
+	return []int64{
+		ssv.histogram_0_1,
+		ssv.histogram_1_10,
+		ssv.histogram_10_100,
+		ssv.histogram_100_1000,
+		ssv.histogram_1000_10000,
+		ssv.histogram_10000_100000,
+		ssv.histogram_100000_1000000,
+		ssv.histogram_1000000_more,
+	}
+}
+
+func (ssv *SqlStatValue) getExecuteAndResultHoldHistogram() []int64 {
+	return []int64{ssv.executeAndResultHoldTime_0_1,
+		ssv.executeAndResultHoldTime_1_10,
+		ssv.executeAndResultHoldTime_10_100,
+		ssv.executeAndResultHoldTime_100_1000,
+		ssv.executeAndResultHoldTime_1000_10000,
+		ssv.executeAndResultHoldTime_10000_100000,
+		ssv.executeAndResultHoldTime_100000_1000000,
+		ssv.executeAndResultHoldTime_1000000_more,
+	}
+}
+
+func (ssv *SqlStatValue) getFetchRowHistogram() []int64 {
+	return []int64{ssv.fetchRowCount_0_1,
+		ssv.fetchRowCount_1_10,
+		ssv.fetchRowCount_10_100,
+		ssv.fetchRowCount_100_1000,
+		ssv.fetchRowCount_1000_10000,
+		ssv.fetchRowCount_10000_more,
+	}
+}
+
+func (ssv *SqlStatValue) getUpdateHistogram() []int64 {
+	return []int64{ssv.updateCount_0_1,
+		ssv.updateCount_1_10,
+		ssv.updateCount_10_100,
+		ssv.updateCount_100_1000,
+		ssv.updateCount_1000_10000,
+		ssv.updateCount_10000_more,
+	}
+}
+
+func (ssv *SqlStatValue) getExecuteCount() int64 {
+	return ssv.executeErrorCount + ssv.executeSuccessCount
+}
+
+func (ssv *SqlStatValue) getExecuteMillisMax() int64 {
+	return ssv.executeSpanNanoMax / (1000 * 1000)
+}
+
+func (ssv *SqlStatValue) getExecuteMillisTotal() int64 {
+	return ssv.executeSpanNanoTotal / (1000 * 1000)
+}
+
+func (ssv *SqlStatValue) getHistogramValues() []int64 {
+	return []int64{
+
+		ssv.histogram_0_1,
+		ssv.histogram_1_10,
+		ssv.histogram_10_100,
+		ssv.histogram_100_1000,
+		ssv.histogram_1000_10000,
+		ssv.histogram_10000_100000,
+		ssv.histogram_100000_1000000,
+		ssv.histogram_1000000_more,
+	}
+}
+
+func (ssv *SqlStatValue) getFetchRowCountHistogramValues() []int64 {
+	return []int64{
+
+		ssv.fetchRowCount_0_1,
+		ssv.fetchRowCount_1_10,
+		ssv.fetchRowCount_10_100,
+		ssv.fetchRowCount_100_1000,
+		ssv.fetchRowCount_1000_10000,
+		ssv.fetchRowCount_10000_more,
+	}
+}
+
+func (ssv *SqlStatValue) getUpdateCountHistogramValues() []int64 {
+	return []int64{
+
+		ssv.updateCount_0_1,
+		ssv.updateCount_1_10,
+		ssv.updateCount_10_100,
+		ssv.updateCount_100_1000,
+		ssv.updateCount_1000_10000,
+		ssv.updateCount_10000_more,
+	}
+}
+
+func (ssv *SqlStatValue) getExecuteAndResultHoldTimeHistogramValues() []int64 {
+	return []int64{
+
+		ssv.executeAndResultHoldTime_0_1,
+		ssv.executeAndResultHoldTime_1_10,
+		ssv.executeAndResultHoldTime_10_100,
+		ssv.executeAndResultHoldTime_100_1000,
+		ssv.executeAndResultHoldTime_1000_10000,
+		ssv.executeAndResultHoldTime_10000_100000,
+		ssv.executeAndResultHoldTime_100000_1000000,
+		ssv.executeAndResultHoldTime_1000000_more,
+	}
+}
+
+func (ssv *SqlStatValue) getResultSetHoldTimeMilis() int64 {
+	return ssv.resultSetHoldTimeNano / (1000 * 1000)
+}
+
+func (ssv *SqlStatValue) getExecuteAndResultSetHoldTimeMilis() int64 {
+	return ssv.executeAndResultSetHoldTime / (1000 * 1000)
+}
+
+func (ssv *SqlStatValue) getData() map[string]interface{} {
+	m := make(map[string]interface{})
+
+	m[idConstStr] = ssv.id
+	m[dataSourceConstStr] = ssv.dataSource
+	m["DataSourceId"] = ssv.dataSourceId
+	m[sqlConstStr] = ssv.sql
+	m[executeCountConstStr] = ssv.getExecuteCount()
+	m[errorCountConstStr] = ssv.executeErrorCount
+
+	m[totalTimeConstStr] = ssv.getExecuteMillisTotal()
+	m["LastTime"] = ssv.executeLastStartTime
+	m[maxTimespanConstStr] = ssv.getExecuteMillisMax()
+	m["LastError"] = ssv.executeErrorLast
+	m[effectedRowCountConstStr] = ssv.updateCount
+
+	m[fetchRowCountConstStr] = ssv.fetchRowCount
+	m["MaxTimespanOccurTime"] = ssv.executeNanoSpanMaxOccurTime
+	m["BatchSizeMax"] = ssv.executeBatchSizeMax
+	m["BatchSizeTotal"] = ssv.executeBatchSizeTotal
+	m[concurrentMaxConstStr] = ssv.concurrentMax
+
+	m[runningCountConstStr] = ssv.runningCount
+
+	if ssv.executeErrorLastMessage != "" {
+		m["LastErrorMessage"] = ssv.executeErrorLastMessage
+		m["LastErrorStackTrace"] = ssv.executeErrorLastStackTrace
+		m["LastErrorTime"] = ssv.executeErrorLastTime
+	} else {
+		m["LastErrorMessage"] = ""
+		m["LastErrorClass"] = ""
+		m["LastErrorStackTrace"] = ""
+		m["LastErrorTime"] = ""
+	}
+
+	m[urlConstStr] = ""
+	m[inTransactionCountConstStr] = ssv.inTransactionCount
+
+	m["Histogram"] = ssv.getHistogramValues()
+	m["LastSlowParameters"] = ssv.lastSlowParameters
+	m["ResultSetHoldTime"] = ssv.getResultSetHoldTimeMilis()
+	m["ExecuteAndResultSetHoldTime"] = ssv.getExecuteAndResultSetHoldTimeMilis()
+	m[fetchRowCountConstStr] = ssv.getFetchRowCountHistogramValues()
+
+	m[effectedRowCountHistogramConstStr] = ssv.getUpdateCountHistogramValues()
+	m[executeAndResultHoldTimeHistogramConstStr] = ssv.getExecuteAndResultHoldTimeHistogramValues()
+	m["EffectedRowCountMax"] = ssv.updateCountMax
+	m["FetchRowCountMax"] = ssv.fetchRowCountMax
+	m[clobOpenCountConstStr] = ssv.clobOpenCount
+
+	m[blobOpenCountConstStr] = ssv.blobOpenCount
+	m["ReadStringLength"] = ssv.readStringLength
+	m["ReadBytesLength"] = ssv.readBytesLength
+	m["InputStreamOpenCount"] = ssv.inputStreamOpenCount
+	m["ReaderOpenCount"] = ssv.readerOpenCount
+
+	m["HASH"] = ssv.sqlHash
+
+	m[executeHoldTimeHistogramConstStr] = ssv.getExecuteHistogram()
+
+	return m
+}
+
+type sqlStat struct {
+	Sql string
+
+	SqlHash int64
+
+	Id string
+
+	ExecuteLastStartTime int64
+
+	ExecuteBatchSizeTotal int64
+
+	ExecuteBatchSizeMax int64
+
+	ExecuteSuccessCount int64
+
+	ExecuteSpanNanoTotal int64
+
+	ExecuteSpanNanoMax int64
+
+	RunningCount int64
+
+	ConcurrentMax int64
+
+	ResultSetHoldTimeNano int64
+
+	ExecuteAndResultSetHoldTime int64
+
+	DataSource string
+
+	File string
+
+	ExecuteNanoSpanMaxOccurTime int64
+
+	ExecuteErrorCount int64
+
+	ExecuteErrorLast error
+
+	ExecuteErrorLastTime int64
+
+	UpdateCount int64
+
+	UpdateCountMax int64
+
+	FetchRowCount int64
+
+	FetchRowCountMax int64
+
+	InTransactionCount int64
+
+	LastSlowParameters string
+
+	Removed int64
+
+	ClobOpenCount int64
+
+	BlobOpenCount int64
+
+	ReadStringLength int64
+
+	ReadBytesLength int64
+
+	InputStreamOpenCount int64
+
+	ReaderOpenCount int64
+
+	Histogram_0_1 int64
+
+	Histogram_1_10 int64
+
+	Histogram_10_100 int64
+
+	Histogram_100_1000 int64
+
+	Histogram_1000_10000 int64
+
+	Histogram_10000_100000 int64
+
+	Histogram_100000_1000000 int64
+
+	Histogram_1000000_more int64
+
+	ExecuteAndResultHoldTime_0_1 int64
+
+	ExecuteAndResultHoldTime_1_10 int64
+
+	ExecuteAndResultHoldTime_10_100 int64
+
+	ExecuteAndResultHoldTime_100_1000 int64
+
+	ExecuteAndResultHoldTime_1000_10000 int64
+
+	ExecuteAndResultHoldTime_10000_100000 int64
+
+	ExecuteAndResultHoldTime_100000_1000000 int64
+
+	ExecuteAndResultHoldTime_1000000_more int64
+
+	FetchRowCount_0_1 int64
+
+	FetchRowCount_1_10 int64
+
+	FetchRowCount_10_100 int64
+
+	FetchRowCount_100_1000 int64
+
+	FetchRowCount_1000_10000 int64
+
+	FetchRowCount_10000_more int64
+
+	UpdateCount_0_1 int64
+
+	UpdateCount_1_10 int64
+
+	UpdateCount_10_100 int64
+
+	UpdateCount_100_1000 int64
+
+	UpdateCount_1000_10000 int64
+
+	UpdateCount_10000_more int64
+
+	DataSourceId string
+}
+
+func NewSqlStat(sql string) *sqlStat {
+	s := new(sqlStat)
+	s.Sql = sql
+	s.Id = "SQL" + generateId()
+	return s
+}
+
+func (s *sqlStat) reset() {
+	s.ExecuteLastStartTime = 0
+
+	s.ExecuteBatchSizeTotal = 0
+	s.ExecuteBatchSizeMax = 0
+
+	s.ExecuteSuccessCount = 0
+	s.ExecuteSpanNanoTotal = 0
+	s.ExecuteSpanNanoMax = 0
+	s.ExecuteNanoSpanMaxOccurTime = 0
+	s.ConcurrentMax = 0
+
+	s.ExecuteErrorCount = 0
+	s.ExecuteErrorLast = nil
+	s.ExecuteErrorLastTime = 0
+
+	s.UpdateCount = 0
+	s.UpdateCountMax = 0
+	s.FetchRowCount = 0
+	s.FetchRowCountMax = 0
+
+	s.Histogram_0_1 = 0
+	s.Histogram_1_10 = 0
+	s.Histogram_10_100 = 0
+	s.Histogram_100_1000 = 0
+	s.Histogram_1000_10000 = 0
+	s.Histogram_10000_100000 = 0
+	s.Histogram_100000_1000000 = 0
+	s.Histogram_1000000_more = 0
+
+	s.LastSlowParameters = ""
+	s.InTransactionCount = 0
+	s.ResultSetHoldTimeNano = 0
+	s.ExecuteAndResultSetHoldTime = 0
+
+	s.FetchRowCount_0_1 = 0
+	s.FetchRowCount_1_10 = 0
+	s.FetchRowCount_10_100 = 0
+	s.FetchRowCount_100_1000 = 0
+	s.FetchRowCount_1000_10000 = 0
+	s.FetchRowCount_10000_more = 0
+
+	s.UpdateCount_0_1 = 0
+	s.UpdateCount_1_10 = 0
+	s.UpdateCount_10_100 = 0
+	s.UpdateCount_100_1000 = 0
+	s.UpdateCount_1000_10000 = 0
+	s.UpdateCount_10000_more = 0
+
+	s.ExecuteAndResultHoldTime_0_1 = 0
+	s.ExecuteAndResultHoldTime_1_10 = 0
+	s.ExecuteAndResultHoldTime_10_100 = 0
+	s.ExecuteAndResultHoldTime_100_1000 = 0
+	s.ExecuteAndResultHoldTime_1000_10000 = 0
+	s.ExecuteAndResultHoldTime_10000_100000 = 0
+	s.ExecuteAndResultHoldTime_100000_1000000 = 0
+	s.ExecuteAndResultHoldTime_1000000_more = 0
+
+	s.BlobOpenCount = 0
+	s.ClobOpenCount = 0
+	s.ReadStringLength = 0
+	s.ReadBytesLength = 0
+	s.InputStreamOpenCount = 0
+	s.ReaderOpenCount = 0
+}
+
+func (s *sqlStat) getValueAndReset() *SqlStatValue {
+	return s.getValue(true)
+}
+
+func (s *sqlStat) getValue(reset bool) *SqlStatValue {
+	ssv := newSqlStatValue()
+	ssv.dataSource = s.DataSource
+	ssv.dataSourceId = s.DataSourceId
+	ssv.sql = s.Sql
+	ssv.sqlHash = s.SqlHash
+	ssv.id = s.Id
+	ssv.executeLastStartTime = s.ExecuteLastStartTime
+	if reset {
+		s.ExecuteLastStartTime = 0
+	}
+
+	ssv.executeBatchSizeTotal = getInt64(&s.ExecuteBatchSizeTotal, reset)
+	ssv.executeBatchSizeMax = getInt64(&s.ExecuteBatchSizeMax, reset)
+	ssv.executeSuccessCount = getInt64(&s.ExecuteSuccessCount, reset)
+	ssv.executeSpanNanoTotal = getInt64(&s.ExecuteSpanNanoTotal, reset)
+	ssv.executeSpanNanoMax = getInt64(&s.ExecuteSpanNanoMax, reset)
+	ssv.executeNanoSpanMaxOccurTime = s.ExecuteNanoSpanMaxOccurTime
+	if reset {
+		s.ExecuteNanoSpanMaxOccurTime = 0
+	}
+
+	ssv.runningCount = s.RunningCount
+	ssv.concurrentMax = getInt64(&s.ConcurrentMax, reset)
+	ssv.executeErrorCount = getInt64(&s.ExecuteErrorCount, reset)
+	ssv.executeErrorLast = s.ExecuteErrorLast
+	if reset {
+		s.ExecuteErrorLast = nil
+	}
+
+	ssv.executeErrorLastTime = s.ExecuteErrorLastTime
+	if reset {
+		ssv.executeErrorLastTime = 0
+	}
+
+	ssv.updateCount = getInt64(&s.UpdateCount, reset)
+	ssv.updateCountMax = getInt64(&s.UpdateCountMax, reset)
+	ssv.fetchRowCount = getInt64(&s.FetchRowCount, reset)
+	ssv.fetchRowCountMax = getInt64(&s.FetchRowCountMax, reset)
+	ssv.histogram_0_1 = getInt64(&s.Histogram_0_1, reset)
+	ssv.histogram_1_10 = getInt64(&s.Histogram_1_10, reset)
+	ssv.histogram_10_100 = getInt64(&s.Histogram_10_100, reset)
+	ssv.histogram_100_1000 = getInt64(&s.Histogram_100_1000, reset)
+	ssv.histogram_1000_10000 = getInt64(&s.Histogram_1000_10000, reset)
+	ssv.histogram_10000_100000 = getInt64(&s.Histogram_10000_100000, reset)
+	ssv.histogram_100000_1000000 = getInt64(&s.Histogram_100000_1000000, reset)
+	ssv.histogram_1000000_more = getInt64(&s.Histogram_1000000_more, reset)
+	ssv.lastSlowParameters = s.LastSlowParameters
+	if reset {
+		s.LastSlowParameters = ""
+	}
+
+	ssv.inTransactionCount = getInt64(&s.InTransactionCount, reset)
+	ssv.resultSetHoldTimeNano = getInt64(&s.ResultSetHoldTimeNano, reset)
+	ssv.executeAndResultSetHoldTime = getInt64(&s.ExecuteAndResultSetHoldTime, reset)
+	ssv.fetchRowCount_0_1 = getInt64(&s.FetchRowCount_0_1, reset)
+	ssv.fetchRowCount_1_10 = getInt64(&s.FetchRowCount_1_10, reset)
+	ssv.fetchRowCount_10_100 = getInt64(&s.FetchRowCount_10_100, reset)
+	ssv.fetchRowCount_100_1000 = getInt64(&s.FetchRowCount_100_1000, reset)
+	ssv.fetchRowCount_1000_10000 = getInt64(&s.FetchRowCount_1000_10000, reset)
+	ssv.fetchRowCount_10000_more = getInt64(&s.FetchRowCount_10000_more, reset)
+	ssv.updateCount_0_1 = getInt64(&s.UpdateCount_0_1, reset)
+	ssv.updateCount_1_10 = getInt64(&s.UpdateCount_1_10, reset)
+	ssv.updateCount_10_100 = getInt64(&s.UpdateCount_10_100, reset)
+	ssv.updateCount_100_1000 = getInt64(&s.UpdateCount_100_1000, reset)
+	ssv.updateCount_1000_10000 = getInt64(&s.UpdateCount_1000_10000, reset)
+	ssv.updateCount_10000_more = getInt64(&s.UpdateCount_10000_more, reset)
+	ssv.executeAndResultHoldTime_0_1 = getInt64(&s.ExecuteAndResultHoldTime_0_1, reset)
+	ssv.executeAndResultHoldTime_1_10 = getInt64(&s.ExecuteAndResultHoldTime_1_10, reset)
+	ssv.executeAndResultHoldTime_10_100 = getInt64(&s.ExecuteAndResultHoldTime_10_100, reset)
+	ssv.executeAndResultHoldTime_100_1000 = getInt64(&s.ExecuteAndResultHoldTime_100_1000, reset)
+	ssv.executeAndResultHoldTime_1000_10000 = getInt64(&s.ExecuteAndResultHoldTime_1000_10000, reset)
+	ssv.executeAndResultHoldTime_10000_100000 = getInt64(&s.ExecuteAndResultHoldTime_10000_100000, reset)
+	ssv.executeAndResultHoldTime_100000_1000000 = getInt64(&s.ExecuteAndResultHoldTime_100000_1000000, reset)
+	ssv.executeAndResultHoldTime_1000000_more = getInt64(&s.ExecuteAndResultHoldTime_1000000_more, reset)
+	ssv.blobOpenCount = getInt64(&s.BlobOpenCount, reset)
+	ssv.clobOpenCount = getInt64(&s.ClobOpenCount, reset)
+	ssv.readStringLength = getInt64(&s.ReadStringLength, reset)
+	ssv.readBytesLength = getInt64(&s.ReadBytesLength, reset)
+	ssv.inputStreamOpenCount = getInt64(&s.InputStreamOpenCount, reset)
+	ssv.readerOpenCount = getInt64(&s.ReaderOpenCount, reset)
+	return ssv
+}
+
+func (s *sqlStat) addUpdateCount(delta int64) {
+	if delta > 0 {
+		atomic.AddInt64(&s.UpdateCount, delta)
+	}
+
+	for {
+		max := atomic.LoadInt64(&s.UpdateCountMax)
+		if delta <= max {
+			break
+		}
+		if atomic.CompareAndSwapInt64(&s.UpdateCountMax, max, delta) {
+			break
+		}
+	}
+
+	if delta < 1 {
+		atomic.AddInt64(&s.UpdateCount_0_1, 1)
+	} else if delta < 10 {
+		atomic.AddInt64(&s.UpdateCount_1_10, 1)
+	} else if delta < 100 {
+		atomic.AddInt64(&s.UpdateCount_10_100, 1)
+	} else if delta < 1000 {
+		atomic.AddInt64(&s.UpdateCount_100_1000, 1)
+	} else if delta < 10000 {
+		atomic.AddInt64(&s.UpdateCount_1000_10000, 1)
+	} else {
+		atomic.AddInt64(&s.UpdateCount_10000_more, 1)
+	}
+}
+
+func (s *sqlStat) incrementClobOpenCount() {
+	atomic.AddInt64(&s.ClobOpenCount, 1)
+}
+
+func (s *sqlStat) incrementBlobOpenCount() {
+	atomic.AddInt64(&s.BlobOpenCount, 1)
+}
+
+func (s *sqlStat) addStringReadLength(length int64) {
+	atomic.AddInt64(&s.ReadStringLength, length)
+}
+
+func (s *sqlStat) addReadBytesLength(length int64) {
+	atomic.AddInt64(&s.ReadBytesLength, length)
+}
+
+func (s *sqlStat) addReaderOpenCount(count int64) {
+	atomic.AddInt64(&s.ReaderOpenCount, count)
+}
+
+func (s *sqlStat) addInputStreamOpenCount(count int64) {
+	atomic.AddInt64(&s.InputStreamOpenCount, count)
+}
+
+func (s *sqlStat) addFetchRowCount(delta int64) {
+	atomic.AddInt64(&s.FetchRowCount, delta)
+	for {
+		max := atomic.LoadInt64(&s.FetchRowCountMax)
+		if delta <= max {
+			break
+		}
+		if atomic.CompareAndSwapInt64(&s.FetchRowCountMax, max, delta) {
+			break
+		}
+	}
+
+	if delta < 1 {
+		atomic.AddInt64(&s.FetchRowCount_0_1, 1)
+	} else if delta < 10 {
+		atomic.AddInt64(&s.FetchRowCount_1_10, 1)
+	} else if delta < 100 {
+		atomic.AddInt64(&s.FetchRowCount_10_100, 1)
+	} else if delta < 1000 {
+		atomic.AddInt64(&s.FetchRowCount_100_1000, 1)
+	} else if delta < 10000 {
+		atomic.AddInt64(&s.FetchRowCount_1000_10000, 1)
+	} else {
+		atomic.AddInt64(&s.FetchRowCount_10000_more, 1)
+	}
+
+}
+
+func (s *sqlStat) addExecuteBatchCount(batchSize int64) {
+	atomic.AddInt64(&s.ExecuteBatchSizeTotal, batchSize)
+
+	for {
+		current := atomic.LoadInt64(&s.ExecuteBatchSizeMax)
+		if current < batchSize {
+			if atomic.CompareAndSwapInt64(&s.ExecuteBatchSizeMax, current, batchSize) {
+				break
+			} else {
+				continue
+			}
+		} else {
+			break
+		}
+	}
+}
+
+func (s *sqlStat) incrementExecuteSuccessCount() {
+	atomic.AddInt64(&s.ExecuteSuccessCount, 1)
+}
+
+func (s *sqlStat) incrementRunningCount() {
+	val := atomic.AddInt64(&s.RunningCount, 1)
+
+	for {
+		max := atomic.LoadInt64(&s.ConcurrentMax)
+		if val > max {
+			if atomic.CompareAndSwapInt64(&s.ConcurrentMax, max, val) {
+				break
+			} else {
+				continue
+			}
+		} else {
+			break
+		}
+	}
+}
+
+func (s *sqlStat) decrementRunningCount() {
+	atomic.AddInt64(&s.RunningCount, -1)
+}
+
+func (s *sqlStat) addExecuteTimeAndResultHoldTimeHistogramRecord(executeType ExecuteTypeEnum, firstResultSet bool, nanoSpan int64, parameters string) {
+	s.addExecuteTime(nanoSpan, parameters)
+
+	if ExecuteQuery != executeType && !firstResultSet {
+		s.executeAndResultHoldTimeHistogramRecord(nanoSpan)
+	}
+}
+
+func (s *sqlStat) executeAndResultHoldTimeHistogramRecord(nanoSpan int64) {
+	millis := nanoSpan / 1000 / 1000
+
+	if millis < 1 {
+		atomic.AddInt64(&s.ExecuteAndResultHoldTime_0_1, 1)
+	} else if millis < 10 {
+		atomic.AddInt64(&s.ExecuteAndResultHoldTime_1_10, 1)
+	} else if millis < 100 {
+		atomic.AddInt64(&s.ExecuteAndResultHoldTime_10_100, 1)
+	} else if millis < 1000 {
+		atomic.AddInt64(&s.ExecuteAndResultHoldTime_100_1000, 1)
+	} else if millis < 10000 {
+		atomic.AddInt64(&s.ExecuteAndResultHoldTime_1000_10000, 1)
+	} else if millis < 100000 {
+		atomic.AddInt64(&s.ExecuteAndResultHoldTime_10000_100000, 1)
+	} else if millis < 1000000 {
+		atomic.AddInt64(&s.ExecuteAndResultHoldTime_100000_1000000, 1)
+	} else {
+		atomic.AddInt64(&s.ExecuteAndResultHoldTime_1000000_more, 1)
+	}
+}
+
+func (s *sqlStat) histogramRecord(nanoSpan int64) {
+	millis := nanoSpan / 1000 / 1000
+
+	if millis < 1 {
+		atomic.AddInt64(&s.Histogram_0_1, 1)
+	} else if millis < 10 {
+		atomic.AddInt64(&s.Histogram_1_10, 1)
+	} else if millis < 100 {
+		atomic.AddInt64(&s.Histogram_10_100, 1)
+	} else if millis < 1000 {
+		atomic.AddInt64(&s.Histogram_100_1000, 1)
+	} else if millis < 10000 {
+		atomic.AddInt64(&s.Histogram_1000_10000, 1)
+	} else if millis < 100000 {
+		atomic.AddInt64(&s.Histogram_10000_100000, 1)
+	} else if millis < 1000000 {
+		atomic.AddInt64(&s.Histogram_100000_1000000, 1)
+	} else {
+		atomic.AddInt64(&s.Histogram_1000000_more, 1)
+	}
+}
+
+func (s *sqlStat) addExecuteTime(nanoSpan int64, parameters string) {
+	atomic.AddInt64(&s.ExecuteSpanNanoTotal, nanoSpan)
+
+	for {
+		current := atomic.LoadInt64(&s.ExecuteSpanNanoMax)
+		if current < nanoSpan {
+			if atomic.CompareAndSwapInt64(&s.ExecuteSpanNanoMax, current, nanoSpan) {
+
+				s.ExecuteNanoSpanMaxOccurTime = time.Now().UnixNano()
+				s.LastSlowParameters = parameters
+
+				break
+			} else {
+				continue
+			}
+		} else {
+			break
+		}
+	}
+
+	s.histogramRecord(nanoSpan)
+}
+
+func (s *sqlStat) getExecuteMillisTotal() int64 {
+	return s.ExecuteSpanNanoTotal / (1000 * 1000)
+}
+
+func (s *sqlStat) getExecuteMillisMax() int64 {
+	return s.ExecuteSpanNanoMax / (1000 * 1000)
+}
+
+func (s *sqlStat) incrementInTransactionCount() {
+	atomic.AddInt64(&s.InTransactionCount, 1)
+}
+
+func (s *sqlStat) getExecuteCount() int64 {
+	return s.ExecuteErrorCount + s.ExecuteSuccessCount
+}
+
+func (s *sqlStat) getData() map[string]interface{} {
+	return s.getValue(false).getData()
+}
+
+func (s *sqlStat) getHistogramValues() []int64 {
+	return []int64{
+
+		s.Histogram_0_1,
+		s.Histogram_1_10,
+		s.Histogram_10_100,
+		s.Histogram_100_1000,
+		s.Histogram_1000_10000,
+		s.Histogram_10000_100000,
+		s.Histogram_100000_1000000,
+		s.Histogram_1000000_more,
+	}
+}
+
+func (s *sqlStat) getHistogramSum() int64 {
+	values := s.getHistogramValues()
+	var sum int64 = 0
+	for i := 0; i < len(values); i++ {
+		sum += values[i]
+	}
+	return sum
+}
+
+func (s *sqlStat) error(err error) {
+	atomic.AddInt64(&s.ExecuteErrorCount, 1)
+	s.ExecuteErrorLastTime = time.Now().UnixNano()
+	s.ExecuteErrorLast = err
+}
+
+func (s *sqlStat) getResultSetHoldTimeMilis() int64 {
+	return s.ResultSetHoldTimeNano / (1000 * 1000)
+}
+
+func (s *sqlStat) getExecuteAndResultSetHoldTimeMilis() int64 {
+	return s.ExecuteAndResultSetHoldTime / (1000 * 1000)
+}
+
+func (s *sqlStat) getFetchRowCountHistogramValues() []int64 {
+	return []int64{
+
+		s.FetchRowCount_0_1,
+		s.FetchRowCount_1_10,
+		s.FetchRowCount_10_100,
+		s.FetchRowCount_100_1000,
+		s.FetchRowCount_1000_10000,
+		s.FetchRowCount_10000_more,
+	}
+}
+
+func (s *sqlStat) getUpdateCountHistogramValues() []int64 {
+	return []int64{
+
+		s.UpdateCount_0_1,
+		s.UpdateCount_1_10,
+		s.UpdateCount_10_100,
+		s.UpdateCount_100_1000,
+		s.UpdateCount_1000_10000,
+		s.UpdateCount_10000_more,
+	}
+}
+
+func (s *sqlStat) getExecuteAndResultHoldTimeHistogramValues() []int64 {
+	return []int64{
+
+		s.ExecuteAndResultHoldTime_0_1,
+		s.ExecuteAndResultHoldTime_1_10,
+		s.ExecuteAndResultHoldTime_10_100,
+		s.ExecuteAndResultHoldTime_100_1000,
+		s.ExecuteAndResultHoldTime_1000_10000,
+		s.ExecuteAndResultHoldTime_10000_100000,
+		s.ExecuteAndResultHoldTime_100000_1000000,
+		s.ExecuteAndResultHoldTime_1000000_more,
+	}
+}
+
+func (s *sqlStat) getExecuteAndResultHoldTimeHistogramSum() int64 {
+	values := s.getExecuteAndResultHoldTimeHistogramValues()
+	var sum int64 = 0
+	for i := 0; i < len(values); i++ {
+		sum += values[i]
+	}
+	return sum
+}
+
+func (s *sqlStat) addResultSetHoldTimeNano(nano int64) {
+	atomic.AddInt64(&s.ResultSetHoldTimeNano, nano)
+}
+
+func (s *sqlStat) addResultSetHoldTimeNano2(statementExecuteNano int64, resultHoldTimeNano int64) {
+	atomic.AddInt64(&s.ResultSetHoldTimeNano, resultHoldTimeNano)
+	atomic.AddInt64(&s.ExecuteAndResultSetHoldTime, statementExecuteNano+resultHoldTimeNano)
+	s.executeAndResultHoldTimeHistogramRecord((statementExecuteNano + resultHoldTimeNano) / 1000 / 1000)
+	atomic.AddInt64(&s.UpdateCount_0_1, 1)
+}
+
+type connectionStatValue struct {
+	id string
+
+	url string
+
+	connCount int64
+
+	activeConnCount int64
+
+	maxActiveConnCount int64
+
+	executeCount int64
+
+	errorCount int64
+
+	stmtCount int64
+
+	activeStmtCount int64
+
+	maxActiveStmtCount int64
+
+	commitCount int64
+
+	rollbackCount int64
+
+	clobOpenCount int64
+
+	blobOpenCount int64
+
+	properties string
+}
+
+func newConnectionStatValue() *connectionStatValue {
+	csv := new(connectionStatValue)
+	return csv
+}
+
+func (csv *connectionStatValue) getData() map[string]interface{} {
+	m := make(map[string]interface{})
+	m[idConstStr] = csv.id
+	m[urlConstStr] = csv.url
+	m[connCountConstStr] = csv.connCount
+	m[activeConnCountConstStr] = csv.activeConnCount
+	m[maxActiveConnCountConstStr] = csv.maxActiveConnCount
+
+	m[stmtCountConstStr] = csv.stmtCount
+	m[activeStmtCountConstStr] = csv.activeStmtCount
+	m[maxActiveStmtCountConstStr] = csv.maxActiveStmtCount
+
+	m[executeCountConstStr] = csv.executeCount
+	m[errorCountConstStr] = csv.errorCount
+	m[commitCountConstStr] = csv.commitCount
+	m[rollbackCountConstStr] = csv.rollbackCount
+
+	m[clobOpenCountConstStr] = csv.clobOpenCount
+	m[blobOpenCountConstStr] = csv.blobOpenCount
+
+	m[propertiesConstStr] = csv.properties
+	return m
+}
+
+type connectionStat struct {
+	id string
+
+	url string
+
+	connCount int64
+
+	activeConnCount int64
+
+	maxActiveConnCount int64
+
+	executeCount int64
+
+	errorCount int64
+
+	stmtCount int64
+
+	activeStmtCount int64
+
+	maxActiveStmtCount int64
+
+	commitCount int64
+
+	rollbackCount int64
+
+	clobOpenCount int64
+
+	blobOpenCount int64
+
+	sqlStatMap map[string]*sqlStat
+
+	maxSqlSize int
+
+	skipSqlCount int64
+
+	lock sync.RWMutex
+
+	properties string
+}
+
+func newConnectionStat(url string) *connectionStat {
+	cs := new(connectionStat)
+	cs.maxSqlSize = StatSqlMaxCount
+	cs.id = "DS" + generateId()
+	cs.url = url
+	cs.sqlStatMap = make(map[string]*sqlStat, 200)
+	return cs
+}
+
+func (cs *connectionStat) createSqlStat(sql string) *sqlStat {
+	cs.lock.Lock()
+	defer cs.lock.Unlock()
+	sqlStat, ok := cs.sqlStatMap[sql]
+	if !ok {
+		sqlStat := NewSqlStat(sql)
+		sqlStat.DataSource = cs.url
+		sqlStat.DataSourceId = cs.id
+		if cs.putSqlStat(sqlStat) {
+			return sqlStat
+		} else {
+			return nil
+		}
+	}
+
+	return sqlStat
+
+}
+
+func (cs *connectionStat) putSqlStat(sqlStat *sqlStat) bool {
+	if cs.maxSqlSize > 0 && len(cs.sqlStatMap) == cs.maxSqlSize {
+		if StatSqlRemoveMode == STAT_SQL_REMOVE_OLDEST {
+			removeSqlStat := cs.eliminateSqlStat()
+			if removeSqlStat.RunningCount > 0 || removeSqlStat.getExecuteCount() > 0 {
+				atomic.AddInt64(&cs.skipSqlCount, 1)
+			}
+			cs.sqlStatMap[sqlStat.Sql] = sqlStat
+			return true
+		} else {
+			if sqlStat.RunningCount > 0 || sqlStat.getExecuteCount() > 0 {
+				atomic.AddInt64(&cs.skipSqlCount, 1)
+			}
+			return false
+		}
+	} else {
+		cs.sqlStatMap[sqlStat.Sql] = sqlStat
+		return true
+	}
+}
+
+func (cs *connectionStat) eliminateSqlStat() *sqlStat {
+	if cs.maxSqlSize > 0 && len(cs.sqlStatMap) == cs.maxSqlSize {
+		if StatSqlRemoveMode == STAT_SQL_REMOVE_OLDEST {
+			for s, item := range cs.sqlStatMap {
+				if item != nil {
+					delete(cs.sqlStatMap, s)
+					return item
+				}
+			}
+		}
+	}
+	return nil
+}
+
+func (cs *connectionStat) getSqlStatMap() map[string]*sqlStat {
+	m := make(map[string]*sqlStat, len(cs.sqlStatMap))
+	cs.lock.Lock()
+	defer cs.lock.Unlock()
+	for s, item := range cs.sqlStatMap {
+		m[s] = item
+	}
+	return m
+}
+
+func (cs *connectionStat) getSqlStatMapAndReset() []*SqlStatValue {
+	stats := make([]*sqlStat, 0, len(cs.sqlStatMap))
+	cs.lock.Lock()
+	defer cs.lock.Unlock()
+
+	for s, stat := range cs.sqlStatMap {
+
+		if stat.getExecuteCount() == 0 && stat.RunningCount == 0 {
+			stat.Removed = 1
+			delete(cs.sqlStatMap, s)
+		} else {
+			stats = append(stats, stat)
+		}
+	}
+
+	values := make([]*SqlStatValue, 0, len(stats))
+	for _, stat := range stats {
+		value := stat.getValueAndReset()
+		if value.getExecuteCount() == 0 && value.runningCount == 0 {
+			continue
+		}
+		values = append(values, value)
+	}
+	return values
+}
+
+func (cs *connectionStat) incrementConn() {
+	atomic.AddInt64(&cs.connCount, 1)
+	atomic.AddInt64(&cs.activeConnCount, 1)
+	count := atomic.LoadInt64(&cs.activeConnCount)
+	if count > atomic.LoadInt64(&cs.maxActiveConnCount) {
+		atomic.StoreInt64(&cs.maxActiveConnCount, count)
+	}
+}
+
+func (cs *connectionStat) decrementConn() {
+	atomic.AddInt64(&cs.activeConnCount, -1)
+}
+
+func (cs *connectionStat) incrementStmt() {
+	atomic.AddInt64(&cs.stmtCount, 1)
+	atomic.AddInt64(&cs.activeStmtCount, 1)
+	count := atomic.LoadInt64(&cs.activeStmtCount)
+	if count > atomic.LoadInt64(&cs.maxActiveStmtCount) {
+		atomic.StoreInt64(&cs.maxActiveStmtCount, count)
+	}
+}
+
+func (cs *connectionStat) decrementStmt() {
+	atomic.AddInt64(&cs.activeStmtCount, -1)
+}
+
+func (cs *connectionStat) decrementStmtByActiveStmtCount(activeStmtCount int64) {
+	atomic.AddInt64(&cs.activeStmtCount, -activeStmtCount)
+}
+
+func (cs *connectionStat) incrementExecuteCount() {
+	atomic.AddInt64(&cs.executeCount, 1)
+}
+
+func (cs *connectionStat) incrementErrorCount() {
+	atomic.AddInt64(&cs.errorCount, 1)
+}
+
+func (cs *connectionStat) incrementCommitCount() {
+	atomic.AddInt64(&cs.commitCount, 1)
+}
+
+func (cs *connectionStat) incrementRollbackCount() {
+	atomic.AddInt64(&cs.rollbackCount, 1)
+}
+
+func (cs *connectionStat) getValue(reset bool) *connectionStatValue {
+	val := newConnectionStatValue()
+	val.id = cs.id
+	val.url = cs.url
+
+	val.connCount = getInt64(&cs.connCount, reset)
+	val.activeConnCount = getInt64(&cs.activeConnCount, false)
+	val.maxActiveConnCount = getInt64(&cs.maxActiveConnCount, false)
+
+	val.stmtCount = getInt64(&cs.stmtCount, reset)
+	val.activeStmtCount = getInt64(&cs.activeStmtCount, false)
+	val.maxActiveStmtCount = getInt64(&cs.maxActiveStmtCount, false)
+
+	val.commitCount = getInt64(&cs.commitCount, reset)
+	val.rollbackCount = getInt64(&cs.rollbackCount, reset)
+	val.executeCount = getInt64(&cs.executeCount, reset)
+	val.errorCount = getInt64(&cs.errorCount, reset)
+
+	val.blobOpenCount = getInt64(&cs.blobOpenCount, reset)
+	val.clobOpenCount = getInt64(&cs.clobOpenCount, reset)
+
+	val.properties = cs.properties
+	return val
+}
+
+func (cs *connectionStat) getData() map[string]interface{} {
+	return cs.getValue(false).getData()
+}
+
+func (cs *connectionStat) getValueAndReset() *connectionStatValue {
+	return cs.getValue(true)
+}
+
+type GoStat struct {
+	connStatMap map[string]*connectionStat
+
+	lock sync.RWMutex
+
+	maxConnSize int
+
+	skipConnCount int64
+}
+
+func newGoStat(maxConnSize int) *GoStat {
+	gs := new(GoStat)
+	if maxConnSize > 0 {
+		gs.maxConnSize = maxConnSize
+	} else {
+		gs.maxConnSize = 1000
+	}
+
+	gs.connStatMap = make(map[string]*connectionStat, 16)
+	return gs
+}
+
+func (gs *GoStat) createConnStat(conn *DmConnection) *connectionStat {
+	url := conn.dmConnector.host + ":" + strconv.Itoa(int(conn.dmConnector.port))
+	gs.lock.Lock()
+	defer gs.lock.Unlock()
+	connstat, ok := gs.connStatMap[url]
+	if !ok {
+		connstat = newConnectionStat(url)
+
+		remove := len(gs.connStatMap) > gs.maxConnSize
+		if remove && connstat.activeConnCount > 0 {
+			atomic.AddInt64(&gs.skipConnCount, 1)
+		}
+
+		gs.connStatMap[url] = connstat
+	}
+
+	return connstat
+}
+
+func (gs *GoStat) getConnStatMap() map[string]*connectionStat {
+	m := make(map[string]*connectionStat, len(gs.connStatMap))
+	gs.lock.Lock()
+	defer gs.lock.Unlock()
+
+	for s, stat := range gs.connStatMap {
+		m[s] = stat
+	}
+	return m
+}
+
+var sqlRowField = []string{rowNumConstStr, dataSourceConstStr, sqlConstStr, executeCountConstStr,
+	totalTimeConstStr, maxTimespanConstStr, inTransactionCountConstStr, errorCountConstStr, effectedRowCountConstStr,
+	fetchRowCountConstStr, runningCountConstStr, concurrentMaxConstStr, executeHoldTimeHistogramConstStr,
+	executeAndResultHoldTimeHistogramConstStr, fetchRowCountHistogramConstStr, effectedRowCountHistogramConstStr}
+
+var sqlColField = []string{"ID", "DataSource", "SQL", "ExecuteCount",
+	"ErrorCount", "TotalTime", "LastTime", "MaxTimespan", "LastError", "EffectedRowCount",
+	"FetchRowCount", "MaxTimespanOccurTime", "BatchSizeMax", "BatchSizeTotal", "ConcurrentMax",
+	"RunningCount", "Name", "File", "LastErrorMessage", "LastErrorClass", "LastErrorStackTrace",
+	"LastErrorTime", "DbType", "URL", "InTransactionCount", "Histogram", "LastSlowParameters",
+	"ResultSetHoldTime", "ExecuteAndResultSetHoldTime", "FetchRowCountHistogram",
+	"EffectedRowCountHistogram", "ExecuteAndResultHoldTimeHistogram", "EffectedRowCountMax",
+	"FetchRowCountMax", "ClobOpenCount"}
+
+const (
+	rowNumConstStr                            = "rowNum"
+	idConstStr                                = "ID"
+	urlConstStr                               = "Url"
+	connCountConstStr                         = "ConnCount"
+	activeConnCountConstStr                   = "ActiveConnCount"
+	maxActiveConnCountConstStr                = "MaxActiveConnCount"
+	stmtCountConstStr                         = "StmtCount"
+	activeStmtCountConstStr                   = "ActiveStmtCount"
+	maxActiveStmtCountConstStr                = "MaxActiveStmtCount"
+	executeCountConstStr                      = "ExecuteCount"
+	errorCountConstStr                        = "ErrorCount"
+	commitCountConstStr                       = "CommitCount"
+	rollbackCountConstStr                     = "RollbackCount"
+	clobOpenCountConstStr                     = "ClobOpenCount"
+	blobOpenCountConstStr                     = "BlobOpenCount"
+	propertiesConstStr                        = "Properties"
+	dataSourceConstStr                        = "DataSource"
+	sqlConstStr                               = "SQL"
+	totalTimeConstStr                         = "TotalTime"
+	maxTimespanConstStr                       = "MaxTimespan"
+	inTransactionCountConstStr                = "InTransactionCount"
+	effectedRowCountConstStr                  = "EffectedRowCount"
+	fetchRowCountConstStr                     = "FetchRowCount"
+	runningCountConstStr                      = "RunningCount"
+	concurrentMaxConstStr                     = "ConcurrentMax"
+	executeHoldTimeHistogramConstStr          = "ExecuteHoldTimeHistogram"
+	executeAndResultHoldTimeHistogramConstStr = "ExecuteAndResultHoldTimeHistogram"
+	fetchRowCountHistogramConstStr            = "FetchRowCountHistogram"
+	effectedRowCountHistogramConstStr         = "EffectedRowCountHistogram"
+)
+
+var dsRowField = []string{rowNumConstStr, urlConstStr, activeConnCountConstStr,
+	maxActiveConnCountConstStr, activeStmtCountConstStr, maxActiveStmtCountConstStr, executeCountConstStr, errorCountConstStr,
+	commitCountConstStr, rollbackCountConstStr}
+
+var dsColField = []string{"ID", "ConnCount", "ActiveConnCount",
+	"MaxActiveConnCount", "StmtCount", "ActiveStmtCount", "MaxActiveStmtCount", "ExecuteCount",
+	"ErrorCount", "CommitCount", "RollbackCount", "ClobOpenCount", "BlobOpenCount"}
+
+const (
+	PROP_NAME_SORT            = "sort"
+	PROP_NAME_SORT_FIELD      = "field"
+	PROP_NAME_SORT_TYPE       = "direction"
+	PROP_NAME_SEARCH          = "search"
+	PROP_NAME_PAGE_NUM        = "pageNum"
+	PROP_NAME_PAGE_SIZE       = "pageSize"
+	PROP_NAME_PAGE_COUNT      = "pageCount"
+	PROP_NAME_TOTAL_ROW_COUNT = "totalRowCount"
+	PROP_NAME_FLUSH_FREQ      = "flushFreq"
+	PROP_NAME_DATASOURCE_ID   = "dataSourceId"
+	PROP_NAME_SQL_ID          = "sqlId"
+
+	URL_SQL               = "sql"
+	URL_SQL_DETAIL        = "sqlDetail"
+	URL_DATASOURCE        = "dataSource"
+	URL_DATASOURCE_DETAIL = "dataSourceDetail"
+
+	RESULT_CODE_SUCCESS = 1
+	RESULT_CODE_ERROR   = -1
+	DEFAULT_PAGE_NUM    = 1
+	DEFAULT_PAGE_SIZE   = int(INT32_MAX)
+	DEFAULT_ORDER_TYPE  = "asc"
+	DEFAULT_ORDERBY     = "DataSourceId"
+)
+
+type StatReader struct {
+	connStat []map[string]interface{}
+
+	connStatColLens []int
+
+	highFreqSqlStat []map[string]interface{}
+
+	highFreqSqlStatColLens []int
+
+	slowSqlStat []map[string]interface{}
+
+	slowSqlStatColLens []int
+}
+
+func newStatReader() *StatReader {
+	sr := new(StatReader)
+	return sr
+}
+
+func (sr *StatReader) readConnStat(retList []string, maxCount int) (bool, []string) {
+	fields := dsRowField
+	isAppend := false
+	if sr.connStat == nil {
+		sr.connStat = sr.getConnStat("", fields)
+		sr.connStatColLens = calcColLens(sr.connStat, fields, COL_MAX_LEN)
+		isAppend = false
+	} else {
+		isAppend = true
+	}
+	var retContent []map[string]interface{}
+	if maxCount > 0 && len(sr.connStat) > maxCount {
+		retContent = sr.connStat[0:maxCount]
+		sr.connStat = sr.connStat[maxCount:len(sr.connStat)]
+	} else {
+		retContent = sr.connStat
+		sr.connStat = nil
+	}
+	retList = append(retList, sr.getFormattedOutput(retContent, fields, sr.connStatColLens, isAppend))
+	return sr.connStat != nil, retList
+}
+
+func (sr *StatReader) readHighFreqSqlStat(retList []string, maxCount int) (bool, []string) {
+	isAppend := false
+	if sr.highFreqSqlStat == nil {
+		sr.highFreqSqlStat = sr.getHighFreqSqlStat(StatHighFreqSqlCount, -1, sqlRowField)
+		sr.highFreqSqlStatColLens = calcColLens(sr.highFreqSqlStat, sqlRowField, COL_MAX_LEN)
+		isAppend = false
+	} else {
+		isAppend = true
+	}
+	var retContent []map[string]interface{}
+	if maxCount > 0 && len(sr.highFreqSqlStat) > maxCount {
+		retContent = sr.highFreqSqlStat[0:maxCount]
+		sr.highFreqSqlStat = sr.highFreqSqlStat[maxCount:len(sr.highFreqSqlStat)]
+	} else {
+		retContent = sr.highFreqSqlStat
+		sr.highFreqSqlStat = nil
+	}
+	retList = append(retList, sr.getFormattedOutput(retContent, sqlRowField, sr.highFreqSqlStatColLens, isAppend))
+	return sr.highFreqSqlStat != nil, retList
+}
+
+func (sr *StatReader) getHighFreqSqlStat(topCount int, sqlId int,
+	fields []string) []map[string]interface{} {
+	var content []map[string]interface{}
+
+	if topCount != 0 {
+		parameters := NewProperties()
+		parameters.Set(PROP_NAME_SORT_FIELD, "ExecuteCount")
+		parameters.Set(PROP_NAME_SORT_TYPE, "desc")
+		parameters.Set(PROP_NAME_PAGE_NUM, "1")
+		parameters.Set(PROP_NAME_PAGE_SIZE, strconv.Itoa(topCount))
+		content = sr.service(URL_SQL, parameters)
+		if sqlId != -1 {
+			matchedContent := make([]map[string]interface{}, 0)
+			for _, sqlStat := range content {
+				idStr := sqlStat["ID"]
+				if idStr == sqlId {
+					matchedContent = append(matchedContent, sqlStat)
+					break
+				}
+			}
+			content = matchedContent
+		}
+	}
+
+	if content == nil {
+		content = make([]map[string]interface{}, 0)
+	} else {
+		i := 1
+		for _, m := range content {
+			m[rowNumConstStr] = i
+			i++
+		}
+	}
+	content = addTitles(content, fields)
+	return content
+}
+
+func (sr *StatReader) readSlowSqlStat(retList []string, maxCount int) (bool, []string) {
+	isAppend := false
+	if sr.slowSqlStat == nil {
+		sr.slowSqlStat = sr.getSlowSqlStat(StatSlowSqlCount, -1, sqlRowField)
+		sr.slowSqlStatColLens = calcColLens(sr.slowSqlStat, sqlRowField,
+			COL_MAX_LEN)
+		isAppend = false
+	} else {
+		isAppend = true
+	}
+	var retContent []map[string]interface{}
+	if maxCount > 0 && len(sr.slowSqlStat) > maxCount {
+		retContent = sr.slowSqlStat[0:maxCount]
+		sr.slowSqlStat = sr.slowSqlStat[maxCount:len(sr.slowSqlStat)]
+	} else {
+		retContent = sr.slowSqlStat
+		sr.slowSqlStat = nil
+	}
+	retList = append(retList, sr.getFormattedOutput(retContent, sqlRowField, sr.slowSqlStatColLens, isAppend))
+	return sr.slowSqlStat != nil, retList
+}
+
+func (sr *StatReader) getSlowSqlStat(topCount int, sqlId int, fields []string) []map[string]interface{} {
+	var content []map[string]interface{}
+
+	if topCount != 0 {
+		parameters := NewProperties()
+		parameters.Set(PROP_NAME_SORT_FIELD, "MaxTimespan")
+		parameters.Set(PROP_NAME_SORT_TYPE, "desc")
+		parameters.Set(PROP_NAME_PAGE_NUM, "1")
+		parameters.Set(PROP_NAME_PAGE_SIZE, strconv.Itoa(topCount))
+
+		content = sr.service(URL_SQL, parameters)
+		if sqlId != -1 {
+			matchedContent := make([]map[string]interface{}, 0)
+			for _, sqlStat := range content {
+				idStr := sqlStat["ID"]
+				if idStr == sqlId {
+					matchedContent = append(matchedContent, sqlStat)
+					break
+				}
+			}
+			content = matchedContent
+		}
+	}
+
+	if content == nil {
+		content = make([]map[string]interface{}, 0)
+	} else {
+		i := 1
+		for _, m := range content {
+			m["rowNum"] = i
+			i++
+		}
+	}
+	content = addTitles(content, fields)
+	return content
+}
+
+func (sr *StatReader) getConnStat(connId string, fields []string) []map[string]interface{} {
+	content := sr.service(URL_DATASOURCE, nil)
+	if connId != "" {
+		matchedContent := make([]map[string]interface{}, 0)
+		for _, dsStat := range content {
+			idStr := dsStat["Identity"]
+			if connId == idStr {
+				matchedContent = append(matchedContent, dsStat)
+				break
+			}
+		}
+		content = matchedContent
+	}
+	if content == nil {
+		content = make([]map[string]interface{}, 0)
+	} else {
+		i := 1
+		for _, m := range content {
+			m["rowNum"] = i
+			i++
+		}
+	}
+	content = addTitles(content, fields)
+	return content
+}
+
+func (sr *StatReader) getFormattedOutput(content []map[string]interface{}, fields []string, colLens []int,
+	isAppend bool) string {
+	return toTable(content, fields, colLens, true, isAppend)
+}
+
+func (sr *StatReader) parseUrl(url string) *Properties {
+	parameters := NewProperties()
+
+	if url == "" || len(strings.TrimSpace(url)) == 0 {
+		return parameters
+	}
+
+	parametersStr := util.StringUtil.SubstringBetween(url, "?", "")
+	if parametersStr == "" || len(parametersStr) == 0 {
+		return parameters
+	}
+
+	parametersArray := strings.Split(parametersStr, "&")
+
+	for _, parameterStr := range parametersArray {
+		index := strings.Index(parametersStr, "=")
+		if index <= 0 {
+			continue
+		}
+
+		name := parameterStr[0:index]
+		value := parameterStr[index+1:]
+		parameters.Set(name, value)
+	}
+	return parameters
+}
+
+func (sr *StatReader) service(url string, params *Properties) []map[string]interface{} {
+	if params != nil {
+		params.SetProperties(sr.parseUrl(url))
+	} else {
+		params = sr.parseUrl(url)
+	}
+
+	if strings.Index(url, URL_SQL) == 0 {
+		array := sr.getSqlStatList(params)
+		array = sr.comparatorOrderBy(array, params)
+		params.Set(PROP_NAME_FLUSH_FREQ, strconv.Itoa(StatFlushFreq))
+		return array
+	} else if strings.Index(url, URL_SQL_DETAIL) == 0 {
+		array := sr.getSqlStatDetailList(params)
+		return array
+	} else if strings.Index(url, URL_DATASOURCE) == 0 {
+		array := sr.getConnStatList(params)
+		array = sr.comparatorOrderBy(array, params)
+		params.Set(PROP_NAME_FLUSH_FREQ, strconv.Itoa(StatFlushFreq))
+		return array
+	} else if strings.Index(url, URL_DATASOURCE_DETAIL) == 0 {
+		array := sr.getConnStatDetailList(params)
+		return array
+	} else {
+		return nil
+	}
+}
+
+func (sr *StatReader) getSqlStatList(params *Properties) []map[string]interface{} {
+	array := make([]map[string]interface{}, 0)
+	connStatMap := goStat.getConnStatMap()
+	var sqlStatMap map[string]*sqlStat
+	for _, connStat := range connStatMap {
+		sqlStatMap = connStat.getSqlStatMap()
+		for _, sqlStat := range sqlStatMap {
+			data := sqlStat.getData()
+			executeCount := data[executeCountConstStr]
+			runningCount := data[runningCountConstStr]
+			if executeCount == 0 && runningCount == 0 {
+				continue
+			}
+
+			array = append(array, data)
+		}
+	}
+
+	return array
+}
+
+func (sr *StatReader) getSqlStatDetailList(params *Properties) []map[string]interface{} {
+	array := make([]map[string]interface{}, 0)
+	connStatMap := goStat.getConnStatMap()
+	var data *sqlStat
+	sqlId := ""
+	dsId := ""
+	if v := params.GetString(PROP_NAME_SQL_ID, ""); v != "" {
+		sqlId = v
+	}
+	if v := params.GetString(PROP_NAME_DATASOURCE_ID, ""); v != "" {
+		dsId = v
+	}
+	if sqlId != "" && dsId != "" {
+		for _, connStat := range connStatMap {
+			if dsId != connStat.id {
+				continue
+			} else {
+				sqlStatMap := connStat.getSqlStatMap()
+				for _, sqlStat := range sqlStatMap {
+
+					if sqlId == sqlStat.Id {
+						data = sqlStat
+						break
+					}
+				}
+			}
+			break
+		}
+	}
+	if data != nil {
+
+		array = append(array, data.getData())
+
+	}
+	return array
+}
+
+func (sr *StatReader) getConnStatList(params *Properties) []map[string]interface{} {
+	array := make([]map[string]interface{}, 0)
+	connStatMap := goStat.getConnStatMap()
+	id := ""
+	if v := params.GetString(PROP_NAME_DATASOURCE_ID, ""); v != "" {
+		id = v
+	}
+	for _, connStat := range connStatMap {
+		data := connStat.getData()
+
+		connCount := data["ConnCount"]
+
+		if connCount == 0 {
+			continue
+		}
+
+		if id != "" {
+			if id == connStat.id {
+				array = append(array, data)
+				break
+			} else {
+				continue
+			}
+		} else {
+
+			array = append(array, data)
+		}
+
+	}
+	return array
+}
+
+func (sr *StatReader) getConnStatDetailList(params *Properties) []map[string]interface{} {
+	array := make([]map[string]interface{}, 0)
+	var data *connectionStat
+	connStatMap := goStat.getConnStatMap()
+	id := ""
+	if v := params.GetString(PROP_NAME_DATASOURCE_ID, ""); v != "" {
+		id = v
+	}
+	if id != "" {
+		for _, connStat := range connStatMap {
+			if id == connStat.id {
+				data = connStat
+				break
+			}
+		}
+	}
+	if data != nil {
+		dataValue := data.getValue(false)
+		m := make(map[string]interface{}, 2)
+		m["name"] = "数据源"
+		m["value"] = dataValue.url
+		array = append(array, m)
+
+		m = make(map[string]interface{}, 2)
+		m["name"] = "总会话数"
+		m["value"] = dataValue.connCount
+		array = append(array, m)
+
+		m = make(map[string]interface{}, 2)
+		m["name"] = "活动会话数"
+		m["value"] = dataValue.activeConnCount
+		array = append(array, m)
+
+		m = make(map[string]interface{}, 2)
+		m["name"] = "活动会话数峰值"
+		m["value"] = dataValue.maxActiveStmtCount
+		array = append(array, m)
+
+		m = make(map[string]interface{}, 2)
+		m["name"] = "总句柄数"
+		m["value"] = dataValue.stmtCount
+		array = append(array, m)
+
+		m = make(map[string]interface{}, 2)
+		m["name"] = "活动句柄数"
+		m["value"] = dataValue.activeStmtCount
+		array = append(array, m)
+
+		m = make(map[string]interface{}, 2)
+		m["name"] = "活动句柄数峰值"
+		m["value"] = dataValue.maxActiveStmtCount
+		array = append(array, m)
+
+		m = make(map[string]interface{}, 2)
+		m["name"] = "执行次数"
+		m["value"] = dataValue.executeCount
+		array = append(array, m)
+
+		m = make(map[string]interface{}, 2)
+		m["name"] = "执行出错次数"
+		m["value"] = dataValue.errorCount
+		array = append(array, m)
+
+		m = make(map[string]interface{}, 2)
+		m["name"] = "提交次数"
+		m["value"] = dataValue.commitCount
+		array = append(array, m)
+
+		m = make(map[string]interface{}, 2)
+		m["name"] = "回滚次数"
+		m["value"] = dataValue.rollbackCount
+		array = append(array, m)
+
+	}
+	return array
+}
+
+type mapSlice struct {
+	m          []map[string]interface{}
+	isDesc     bool
+	orderByKey string
+}
+
+func newMapSlice(m []map[string]interface{}, isDesc bool, orderByKey string) *mapSlice {
+	ms := new(mapSlice)
+	ms.m = m
+	ms.isDesc = isDesc
+	ms.orderByKey = orderByKey
+	return ms
+}
+
+func (ms mapSlice) Len() int { return len(ms.m) }
+
+func (ms mapSlice) Less(i, j int) bool {
+	m1 := ms.m[i]
+	m2 := ms.m[j]
+	v1 := m1[ms.orderByKey]
+	v2 := m2[ms.orderByKey]
+	if v1 == nil {
+		return true
+	} else if v2 == nil {
+		return false
+	}
+
+	switch v1.(type) {
+	case int64:
+		return v1.(int64) < v2.(int64)
+	case float64:
+		return v1.(float64) < v2.(float64)
+	default:
+		return true
+	}
+}
+
+func (ms mapSlice) Swap(i, j int) {
+	ms.m[i], ms.m[j] = ms.m[j], ms.m[i]
+}
+
+func (sr *StatReader) comparatorOrderBy(array []map[string]interface{}, params *Properties) []map[string]interface{} {
+	if array == nil {
+		array = make([]map[string]interface{}, 0)
+	}
+
+	orderBy := DEFAULT_ORDERBY
+	orderType := DEFAULT_ORDER_TYPE
+	pageNum := DEFAULT_PAGE_NUM
+	pageSize := DEFAULT_PAGE_SIZE
+	if params != nil {
+		if v := params.GetTrimString(PROP_NAME_SORT_FIELD, ""); v != "" {
+			orderBy = v
+		}
+
+		if v := params.GetTrimString(PROP_NAME_SORT_TYPE, ""); v != "" {
+			orderType = v
+		}
+
+		if v := params.GetTrimString(PROP_NAME_PAGE_NUM, ""); v != "" {
+			var err error
+			pageNum, err = strconv.Atoi(v)
+			if err != nil {
+				pageNum = DEFAULT_PAGE_NUM
+			}
+		}
+		if v := params.GetTrimString(PROP_NAME_PAGE_SIZE, ""); v != "" {
+			var err error
+			pageSize, err = strconv.Atoi(v)
+			if err != nil {
+				pageSize = DEFAULT_PAGE_SIZE
+			}
+		}
+	}
+
+	rowCount := len(array)
+	pageCount := int(math.Ceil(float64(rowCount * 1.0 / pageSize)))
+	if pageCount < 1 {
+		pageCount = 1
+	}
+
+	if pageNum > pageCount {
+		pageNum = pageCount
+	}
+
+	if len(array) > 0 {
+
+		if orderBy != "" {
+			sort.Sort(newMapSlice(array, !(DEFAULT_ORDER_TYPE == orderType), orderBy))
+		}
+
+		fromIndex := (pageNum - 1) * pageSize
+
+		toIndex := pageNum * pageSize
+		if toIndex > rowCount {
+			toIndex = rowCount
+		}
+		array = array[fromIndex:toIndex]
+	}
+	sr.resetPageInfo(params, rowCount, pageCount, pageNum)
+	return array
+}
+
+func (sr *StatReader) resetPageInfo(params *Properties, rowCount int, pageCount int, pageNum int) {
+
+	if params != nil {
+		v := params.GetString(PROP_NAME_PAGE_SIZE, "")
+		if v != "" {
+
+			params.Set(PROP_NAME_PAGE_COUNT, strconv.Itoa(pageCount))
+			params.Set(PROP_NAME_TOTAL_ROW_COUNT, strconv.Itoa(rowCount))
+			params.Set(PROP_NAME_PAGE_NUM, strconv.Itoa(pageNum))
+		}
+	}
+}
+
+const COL_MAX_LEN = 32
+
+func calcColLens(objList []map[string]interface{}, fields []string, maxColLen int) []int {
+
+	colLen := 0
+	colVal := ""
+	colLens := make([]int, len(fields))
+	for _, obj := range objList {
+		for i := 0; i < len(fields); i++ {
+			colVal = getColValue(obj[fields[i]])
+			colLen = len(colVal)
+			if colLen > colLens[i] {
+				colLens[i] = colLen
+			}
+		}
+	}
+	if maxColLen > 0 {
+		for i := 0; i < len(fields); i++ {
+			if colLens[i] > maxColLen {
+				colLens[i] = maxColLen
+			}
+		}
+	}
+	return colLens
+}
+
+func addTitles(objList []map[string]interface{}, fields []string) []map[string]interface{} {
+	titleMap := make(map[string]interface{}, len(fields))
+	for i := 0; i < len(fields); i++ {
+		titleMap[fields[i]] = fields[i]
+	}
+
+	dst := append(objList, titleMap)
+	copy(dst[1:], dst[:len(dst)-1])
+	dst[0] = titleMap
+	return dst
+}
+
+func toTable(objList []map[string]interface{}, fields []string, colLens []int,
+	showAll bool, append bool) string {
+	if fields == nil || objList == nil {
+		return ""
+	}
+
+	if colLens == nil {
+		colLens = calcColLens(objList, fields, COL_MAX_LEN)
+	}
+
+	output := &strings.Builder{}
+	if !append {
+		sepLine(output, colLens)
+	}
+
+	for _, obj := range objList {
+		objMore := obj
+		for objMore != nil {
+			objMore = formateLine(output, objMore, fields, colLens, showAll)
+		}
+		sepLine(output, colLens)
+	}
+
+	return output.String()
+}
+
+func formateLine(output *strings.Builder, obj map[string]interface{}, fields []string, colLens []int,
+	showAll bool) map[string]interface{} {
+	hasMore := false
+	objMore := make(map[string]interface{})
+	colLen := 0
+	colVal := ""
+	for i := 0; i < len(fields); i++ {
+		colVal = getColValue(obj[fields[i]])
+
+		colLen = len(colVal)
+		if colLen <= colLens[i] {
+			output.WriteString("|")
+			output.WriteString(colVal)
+			blanks(output, colLens[i]-colLen)
+			if showAll {
+				objMore[fields[i]] = ""
+			}
+		} else {
+			output.WriteString("|")
+			if showAll {
+				output.WriteString(colVal[0:colLens[i]])
+				objMore[fields[i]] = colVal[colLens[i]:]
+				hasMore = true
+			} else {
+				output.WriteString(colVal[0:colLens[i]-3] + "...")
+			}
+		}
+	}
+	output.WriteString("|")
+	output.WriteString(util.StringUtil.LineSeparator())
+
+	if hasMore {
+		return objMore
+	} else {
+		return nil
+	}
+}
+
+func sepLine(output *strings.Builder, colLens []int) {
+	output.WriteString("+")
+	for _, colLen := range colLens {
+		for i := 0; i < colLen; i++ {
+			output.WriteString("+")
+		}
+		output.WriteString("+")
+	}
+	output.WriteString(util.StringUtil.LineSeparator())
+}
+
+func blanks(output *strings.Builder, count int) {
+	for count > 0 {
+		output.WriteString(" ")
+		count--
+	}
+}
+
+func getColValue(colObj interface{}) string {
+	var colVal string
+	if colObj == nil {
+		colVal = ""
+	} else {
+		colVal = fmt.Sprint(colObj)
+	}
+
+	colVal = strings.Replace(colVal, "\t", "", -1)
+	colVal = strings.Replace(colVal, "\n", "", -1)
+	colVal = strings.Replace(colVal, "\r", "", -1)
+
+	return colVal
+}
+
+const (
+	READ_MAX_SIZE = 100
+)
+
+type statFlusher struct {
+	sr         *StatReader
+	logList    []string
+	date       string
+	logFile    *os.File
+	flushFreq  int
+	filePath   string
+	filePrefix string
+	buffer     *Dm_build_283
+}
+
+func newStatFlusher() *statFlusher {
+	sf := new(statFlusher)
+	sf.sr = newStatReader()
+	sf.logList = make([]string, 0, 32)
+	sf.date = time.Now().Format("2006-01-02")
+	sf.flushFreq = StatFlushFreq
+	sf.filePath = StatDir
+	sf.filePrefix = "dm_go_stat"
+	sf.buffer = Dm_build_287()
+	return sf
+}
+
+func (sf *statFlusher) isConnStatEnabled() bool {
+	return StatEnable
+}
+
+func (sf *statFlusher) isSlowSqlStatEnabled() bool {
+	return StatEnable
+}
+
+func (sf *statFlusher) isHighFreqSqlStatEnabled() bool {
+	return StatEnable
+}
+
+func (sf *statFlusher) doRun() {
+
+	for {
+		if len(goStat.connStatMap) > 0 {
+			sf.logList = append(sf.logList, time.Now().String())
+			if sf.isConnStatEnabled() {
+				sf.logList = append(sf.logList, "#connection stat")
+				hasMore := true
+				for hasMore {
+					hasMore, sf.logList = sf.sr.readConnStat(sf.logList, READ_MAX_SIZE)
+					sf.writeAndFlush(sf.logList, 0, len(sf.logList))
+					sf.logList = sf.logList[0:0]
+				}
+			}
+			if sf.isHighFreqSqlStatEnabled() {
+				sf.logList = append(sf.logList, "#top "+strconv.Itoa(StatHighFreqSqlCount)+" high freq sql stat")
+				hasMore := true
+				for hasMore {
+					hasMore, sf.logList = sf.sr.readHighFreqSqlStat(sf.logList, READ_MAX_SIZE)
+					sf.writeAndFlush(sf.logList, 0, len(sf.logList))
+					sf.logList = sf.logList[0:0]
+				}
+			}
+			if sf.isSlowSqlStatEnabled() {
+				sf.logList = append(sf.logList, "#top "+strconv.Itoa(StatSlowSqlCount)+" slow sql stat")
+				hasMore := true
+				for hasMore {
+					hasMore, sf.logList = sf.sr.readSlowSqlStat(sf.logList, READ_MAX_SIZE)
+					sf.writeAndFlush(sf.logList, 0, len(sf.logList))
+					sf.logList = sf.logList[0:0]
+				}
+			}
+			sf.logList = append(sf.logList, util.StringUtil.LineSeparator())
+			sf.logList = append(sf.logList, util.StringUtil.LineSeparator())
+			sf.writeAndFlush(sf.logList, 0, len(sf.logList))
+			sf.logList = sf.logList[0:0]
+			time.Sleep(time.Duration(StatFlushFreq) * time.Second)
+		}
+	}
+}
+
+func (sf *statFlusher) writeAndFlush(logs []string, startOff int, l int) {
+	var bytes []byte
+	for i := startOff; i < startOff+l; i++ {
+		bytes = []byte(logs[i] + util.StringUtil.LineSeparator())
+
+		sf.buffer.Dm_build_309(bytes, 0, len(bytes))
+
+		if sf.buffer.Dm_build_288() >= FLUSH_SIZE {
+			sf.doFlush(sf.buffer)
+		}
+	}
+
+	if sf.buffer.Dm_build_288() > 0 {
+		sf.doFlush(sf.buffer)
+	}
+}
+
+func (sf *statFlusher) doFlush(buffer *Dm_build_283) {
+	if sf.needCreateNewFile() {
+		sf.closeCurrentFile()
+		sf.logFile = sf.createNewFile()
+	}
+	if sf.logFile != nil {
+		buffer.Dm_build_303(sf.logFile, buffer.Dm_build_288())
+	}
+}
+func (sf *statFlusher) closeCurrentFile() {
+	if sf.logFile != nil {
+		sf.logFile.Close()
+		sf.logFile = nil
+	}
+}
+func (sf *statFlusher) createNewFile() *os.File {
+	sf.date = time.Now().Format("2006-01-02")
+	fileName := sf.filePrefix + "_" + sf.date + "_" + strconv.Itoa(time.Now().Nanosecond()) + ".txt"
+	sf.filePath = StatDir
+	if len(sf.filePath) > 0 {
+		if _, err := os.Stat(sf.filePath); err != nil {
+			os.MkdirAll(sf.filePath, 0755)
+		}
+		if _, err := os.Stat(sf.filePath + fileName); err != nil {
+			logFile, err := os.Create(sf.filePath + fileName)
+			if err != nil {
+				fmt.Println(err)
+				return nil
+			}
+			return logFile
+		}
+	}
+	return nil
+}
+func (sf *statFlusher) needCreateNewFile() bool {
+	now := time.Now().Format("2006-01-02")
+	fileInfo, err := sf.logFile.Stat()
+	return now != sf.date || err != nil || sf.logFile == nil || fileInfo.Size() > int64(MAX_FILE_SIZE)
+}

+ 8 - 0
go.mod

@@ -0,0 +1,8 @@
+module gitee.com/chunanyong/dm
+
+go 1.13
+
+require (
+	github.com/golang/snappy v0.0.1
+	golang.org/x/text v0.3.2
+)

+ 5 - 0
go.sum

@@ -0,0 +1,5 @@
+github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
+github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

+ 923 - 0
h.go

@@ -0,0 +1,923 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"math"
+	"strconv"
+	"strings"
+	"time"
+	"unicode"
+)
+
+func encodeByString(x string, column column, conn DmConnection) ([]byte, error) {
+	dt := make([]int, DT_LEN)
+	if _, err := toDTFromString(x, dt); err != nil {
+		return nil, err
+	}
+	return encode(dt, column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
+}
+
+func encodeByTime(x time.Time, column column, conn DmConnection) ([]byte, error) {
+	dt := toDTFromTime(x)
+	return encode(dt, column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
+}
+
+func toTimeFromString(str string, ltz int) time.Time {
+	dt := make([]int, DT_LEN)
+	toDTFromString(str, dt)
+	return toTimeFromDT(dt, ltz)
+}
+
+func toTimeFromDT(dt []int, ltz int) time.Time {
+	var year, month, day, hour, minute, second, nsec, tz int
+
+	year = dt[OFFSET_YEAR]
+
+	if dt[OFFSET_MONTH] > 0 {
+		month = dt[OFFSET_MONTH]
+	} else {
+		month = 1
+	}
+
+	if dt[OFFSET_DAY] > 0 {
+		day = dt[OFFSET_DAY]
+	} else {
+		day = 1
+	}
+
+	hour = dt[OFFSET_HOUR]
+	minute = dt[OFFSET_MINUTE]
+	second = dt[OFFSET_SECOND]
+	nsec = dt[OFFSET_NANOSECOND]
+	if dt[OFFSET_TIMEZONE] == INVALID_VALUE {
+		tz = ltz * 60
+	} else {
+		tz = dt[OFFSET_TIMEZONE] * 60
+	}
+	return time.Date(year, time.Month(month), day, hour, minute, second, nsec, time.FixedZone("", tz))
+}
+
+func decode(value []byte, isBdta bool, column column, ltz int, dtz int) []int {
+	var dt []int
+	if isBdta {
+		dt = dmdtDecodeBdta(value)
+	} else {
+		dt = dmdtDecodeFast(value)
+	}
+
+	if column.mask == MASK_LOCAL_DATETIME {
+		transformTZ(dt, dtz, ltz)
+	}
+
+	return dt
+}
+
+func dmdtDecodeFast(value []byte) []int {
+	dt := make([]int, DT_LEN)
+	dt[OFFSET_TIMEZONE] = INVALID_VALUE
+
+	dtype := 0
+	if len(value) == DATE_PREC {
+		dtype = DATE
+	} else if len(value) == TIME_PREC {
+		dtype = TIME
+	} else if len(value) == TIME_TZ_PREC {
+		dtype = TIME_TZ
+	} else if len(value) == DATETIME_PREC {
+		dtype = DATETIME
+	} else if len(value) == DATETIME2_PREC {
+		dtype = DATETIME2
+	} else if len(value) == DATETIME_TZ_PREC {
+		dtype = DATETIME_TZ
+	} else if len(value) == DATETIME2_TZ_PREC {
+		dtype = DATETIME2_TZ
+	}
+
+	if dtype == DATE {
+
+		dt[OFFSET_YEAR] = int(Dm_build_1.Dm_build_98(value, 0)) & 0x7FFF
+		if dt[OFFSET_YEAR] > 9999 {
+			dt[OFFSET_YEAR] = int(int16(dt[OFFSET_YEAR] | 0x8000))
+		}
+
+		dt[OFFSET_MONTH] = ((int(value[1]) >> 7) & 0x1) + ((int(value[2]) & 0x07) << 1)
+
+		dt[OFFSET_DAY] = ((int(value[2]) & 0xF8) >> 3) & 0x1f
+	} else if dtype == TIME {
+		dt[OFFSET_HOUR] = int(value[0]) & 0x1F
+		dt[OFFSET_MINUTE] = ((int(value[0]) >> 5) & 0x07) + ((int(value[1]) & 0x07) << 3)
+		dt[OFFSET_SECOND] = ((int(value[1]) >> 3) & 0x1f) + ((int(value[2]) & 0x01) << 5)
+		dt[OFFSET_NANOSECOND] = ((int(value[2]) >> 1) & 0x7f) + ((int(value[3]) & 0x00ff) << 7) + ((int(value[4]) & 0x1F) << 15)
+		dt[OFFSET_NANOSECOND] *= 1000
+	} else if dtype == TIME_TZ {
+		dt[OFFSET_HOUR] = int(value[0]) & 0x1F
+		dt[OFFSET_MINUTE] = ((int(value[0]) >> 5) & 0x07) + ((int(value[1]) & 0x07) << 3)
+		dt[OFFSET_SECOND] = ((int(value[1]) >> 3) & 0x1f) + ((int(value[2]) & 0x01) << 5)
+		dt[OFFSET_NANOSECOND] = ((int(value[2]) >> 1) & 0x7f) + ((int(value[3]) & 0x00ff) << 7) + ((int(value[4]) & 0x1F) << 15)
+		dt[OFFSET_NANOSECOND] *= 1000
+		dt[OFFSET_TIMEZONE] = int(Dm_build_1.Dm_build_98(value, 5))
+	} else if dtype == DATETIME {
+
+		dt[OFFSET_YEAR] = int(Dm_build_1.Dm_build_98(value, 0)) & 0x7FFF
+		if dt[OFFSET_YEAR] > 9999 {
+			dt[OFFSET_YEAR] = int(int16(dt[OFFSET_YEAR] | 0x8000))
+		}
+
+		dt[OFFSET_MONTH] = ((int(value[1]) >> 7) & 0x1) + ((int(value[2]) & 0x07) << 1)
+
+		dt[OFFSET_DAY] = ((int(value[2]) & 0xF8) >> 3) & 0x1f
+
+		dt[OFFSET_HOUR] = (int(value[3]) & 0x1F)
+
+		dt[OFFSET_MINUTE] = ((int(value[3]) >> 5) & 0x07) + ((int(value[4]) & 0x07) << 3)
+
+		dt[OFFSET_SECOND] = ((int(value[4]) >> 3) & 0x1f) + ((int(value[5]) & 0x01) << 5)
+
+		dt[OFFSET_NANOSECOND] = ((int(value[5]) >> 1) & 0x7f) + ((int(value[6]) & 0x00ff) << 7) + ((int(value[7]) & 0x1F) << 15)
+		dt[OFFSET_NANOSECOND] *= 1000
+	} else if dtype == DATETIME_TZ {
+
+		dt[OFFSET_YEAR] = int(Dm_build_1.Dm_build_98(value, 0)) & 0x7FFF
+		if dt[OFFSET_YEAR] > 9999 {
+			dt[OFFSET_YEAR] = int(int16(dt[OFFSET_YEAR] | 0x8000))
+		}
+
+		dt[OFFSET_MONTH] = ((int(value[1]) >> 7) & 0x1) + ((int(value[2]) & 0x07) << 1)
+
+		dt[OFFSET_DAY] = ((int(value[2]) & 0xF8) >> 3) & 0x1f
+
+		dt[OFFSET_HOUR] = (int(value[3]) & 0x1F)
+
+		dt[OFFSET_MINUTE] = ((int(value[3]) >> 5) & 0x07) + ((int(value[4]) & 0x07) << 3)
+
+		dt[OFFSET_SECOND] = ((int(value[4]) >> 3) & 0x1f) + ((int(value[5]) & 0x01) << 5)
+
+		dt[OFFSET_NANOSECOND] = ((int(value[5]) >> 1) & 0x7f) + ((int(value[6]) & 0x00ff) << 7) + ((int(value[7]) & 0x1F) << 15)
+		dt[OFFSET_NANOSECOND] *= 1000
+
+		dt[OFFSET_TIMEZONE] = int(Dm_build_1.Dm_build_98(value, len(value)-2))
+	} else if dtype == DATETIME2 {
+
+		dt[OFFSET_YEAR] = int(Dm_build_1.Dm_build_98(value, 0)) & 0x7FFF
+		if dt[OFFSET_YEAR] > 9999 {
+			dt[OFFSET_YEAR] = int(int16(dt[OFFSET_YEAR] | 0x8000))
+		}
+
+		dt[OFFSET_MONTH] = ((int(value[1]) >> 7) & 0x1) + ((int(value[2]) & 0x07) << 1)
+
+		dt[OFFSET_DAY] = ((int(value[2]) & 0xF8) >> 3) & 0x1f
+
+		dt[OFFSET_HOUR] = (int(value[3]) & 0x1F)
+
+		dt[OFFSET_MINUTE] = ((int(value[3]) >> 5) & 0x07) + ((int(value[4]) & 0x07) << 3)
+
+		dt[OFFSET_SECOND] = ((int(value[4]) >> 3) & 0x1f) + ((int(value[5]) & 0x01) << 5)
+
+		dt[OFFSET_NANOSECOND] = ((int(value[5]) >> 1) & 0x7f) + ((int(value[6]) & 0x00ff) << 7) + ((int(value[7]) & 0x00ff) << 15) + ((int(value[8]) & 0x7F) << 23)
+	} else if dtype == DATETIME2_TZ {
+
+		dt[OFFSET_YEAR] = int(Dm_build_1.Dm_build_98(value, 0)) & 0x7FFF
+		if dt[OFFSET_YEAR] > 9999 {
+			dt[OFFSET_YEAR] = int(int16(dt[OFFSET_YEAR] | 0x8000))
+		}
+
+		dt[OFFSET_MONTH] = ((int(value[1]) >> 7) & 0x1) + ((int(value[2]) & 0x07) << 1)
+
+		dt[OFFSET_DAY] = ((int(value[2]) & 0xF8) >> 3) & 0x1f
+
+		dt[OFFSET_HOUR] = (int(value[3]) & 0x1F)
+
+		dt[OFFSET_MINUTE] = ((int(value[3]) >> 5) & 0x07) + ((int(value[4]) & 0x07) << 3)
+
+		dt[OFFSET_SECOND] = ((int(value[4]) >> 3) & 0x1f) + ((int(value[5]) & 0x01) << 5)
+
+		dt[OFFSET_NANOSECOND] = ((int(value[5]) >> 1) & 0x7f) + ((int(value[6]) & 0x00ff) << 7) + ((int(value[7]) & 0x00ff) << 15) + ((int(value[8]) & 0x7F) << 23)
+
+		dt[OFFSET_TIMEZONE] = int(Dm_build_1.Dm_build_98(value, len(value)-2))
+	}
+	return dt
+}
+
+func dmdtDecodeBdta(value []byte) []int {
+	dt := make([]int, DT_LEN)
+	dt[OFFSET_YEAR] = int(Dm_build_1.Dm_build_98(value, 0))
+	dt[OFFSET_MONTH] = int(value[2] & 0xFF)
+	dt[OFFSET_DAY] = int(value[3] & 0xFF)
+	dt[OFFSET_HOUR] = int(value[4] & 0xFF)
+	dt[OFFSET_MINUTE] = int(value[5] & 0xFF)
+	dt[OFFSET_SECOND] = int(value[6] & 0xFF)
+	dt[OFFSET_NANOSECOND] = int((value[7] & 0xFF) + (value[8] << 8) + (value[9] << 16))
+	dt[OFFSET_TIMEZONE] = int(Dm_build_1.Dm_build_98(value, 10))
+
+	if len(value) > 12 {
+
+		dt[OFFSET_NANOSECOND] += int(value[12] << 24)
+	}
+	return dt
+}
+
+func dtToStringByOracleFormat(dt []int, oracleFormatPattern string, scale int32, language int) string {
+	return format(dt, oracleFormatPattern, scale, language)
+}
+
+func dtToString(dt []int, dtype int, scale int) string {
+	switch dtype {
+	case DATE:
+		return formatYear(dt[OFFSET_YEAR]) + "-" + format2(dt[OFFSET_MONTH]) + "-" + format2(dt[OFFSET_DAY])
+
+	case TIME:
+		if scale > 0 {
+			return format2(dt[OFFSET_HOUR]) + ":" + format2(dt[OFFSET_MINUTE]) + ":" + format2(dt[OFFSET_SECOND]) + "." + formatMilliSecond(dt[OFFSET_NANOSECOND], scale)
+		} else {
+			return format2(dt[OFFSET_HOUR]) + ":" + format2(dt[OFFSET_MINUTE]) + ":" + format2(dt[OFFSET_SECOND])
+		}
+
+	case TIME_TZ:
+		if scale > 0 {
+			return format2(dt[OFFSET_HOUR]) + ":" + format2(dt[OFFSET_MINUTE]) + ":" + format2(dt[OFFSET_SECOND]) + "." + formatMilliSecond(dt[OFFSET_NANOSECOND], scale) + " " + formatTZ(dt[OFFSET_TIMEZONE])
+		} else {
+			return format2(dt[OFFSET_HOUR]) + ":" + format2(dt[OFFSET_MINUTE]) + ":" + format2(dt[OFFSET_SECOND]) + " " + formatTZ(dt[OFFSET_TIMEZONE])
+		}
+
+	case DATETIME, DATETIME2:
+		if scale > 0 {
+			return formatYear(dt[OFFSET_YEAR]) + "-" + format2(dt[OFFSET_MONTH]) + "-" + format2(dt[OFFSET_DAY]) + " " + format2(dt[OFFSET_HOUR]) + ":" + format2(dt[OFFSET_MINUTE]) + ":" + format2(dt[OFFSET_SECOND]) + "." + formatMilliSecond(dt[OFFSET_NANOSECOND], scale)
+		} else {
+			return formatYear(dt[OFFSET_YEAR]) + "-" + format2(dt[OFFSET_MONTH]) + "-" + format2(dt[OFFSET_DAY]) + " " + format2(dt[OFFSET_HOUR]) + ":" + format2(dt[OFFSET_MINUTE]) + ":" + format2(dt[OFFSET_SECOND])
+		}
+
+	case DATETIME_TZ, DATETIME2_TZ:
+		if scale > 0 {
+			return formatYear(dt[OFFSET_YEAR]) + "-" + format2(dt[OFFSET_MONTH]) + "-" + format2(dt[OFFSET_DAY]) + " " + format2(dt[OFFSET_HOUR]) + ":" + format2(dt[OFFSET_MINUTE]) + ":" + format2(dt[OFFSET_SECOND]) + "." + formatMilliSecond(dt[OFFSET_NANOSECOND], scale) + " " + formatTZ(dt[OFFSET_TIMEZONE])
+		} else {
+			return formatYear(dt[OFFSET_YEAR]) + "-" + format2(dt[OFFSET_MONTH]) + "-" + format2(dt[OFFSET_DAY]) + " " + format2(dt[OFFSET_HOUR]) + ":" + format2(dt[OFFSET_MINUTE]) + ":" + format2(dt[OFFSET_SECOND]) + " " + formatTZ(dt[OFFSET_TIMEZONE])
+		}
+	}
+
+	return ""
+}
+
+func formatYear(value int) string {
+	if value >= 0 {
+		if value < 10 {
+			return "000" + strconv.FormatInt(int64(value), 10)
+		} else if value < 100 {
+			return "00" + strconv.FormatInt(int64(value), 10)
+		} else if value < 1000 {
+			return "0" + strconv.FormatInt(int64(value), 10)
+		} else {
+			return strconv.FormatInt(int64(value), 10)
+		}
+	} else {
+		if value > -10 {
+			return "-000" + strconv.FormatInt(int64(-value), 10)
+		} else if value > -100 {
+			return "-00" + strconv.FormatInt(int64(-value), 10)
+		} else if value > -1000 {
+			return "-0" + strconv.FormatInt(int64(-value), 10)
+		} else {
+			return strconv.FormatInt(int64(value), 10)
+		}
+	}
+}
+
+func format2(value int) string {
+	if value < 10 {
+		return "0" + strconv.FormatInt(int64(value), 10)
+	} else {
+		return strconv.FormatInt(int64(value), 10)
+	}
+}
+
+func formatMilliSecond(ms int, prec int) string {
+	var ret string
+	if ms < 10 {
+		ret = "00000000" + strconv.FormatInt(int64(ms), 10)
+	} else if ms < 100 {
+		ret = "0000000" + strconv.FormatInt(int64(ms), 10)
+	} else if ms < 1000 {
+		ret = "000000" + strconv.FormatInt(int64(ms), 10)
+	} else if ms < 10000 {
+		ret = "00000" + strconv.FormatInt(int64(ms), 10)
+	} else if ms < 100000 {
+		ret = "0000" + strconv.FormatInt(int64(ms), 10)
+	} else if ms < 1000000 {
+		ret = "000" + strconv.FormatInt(int64(ms), 10)
+	} else if ms < 10000000 {
+		ret = "00" + strconv.FormatInt(int64(ms), 10)
+	} else if ms < 100000000 {
+		ret = "0" + strconv.FormatInt(int64(ms), 10)
+	} else {
+		ret = strconv.FormatInt(int64(ms), 10)
+	}
+
+	if prec < NANOSECOND_DIGITS {
+		ret = ret[:prec]
+	}
+	return ret
+}
+
+func formatTZ(tz int) string {
+	tz_hour := int(math.Abs(float64(tz / 60)))
+	tz_min := int(math.Abs(float64(tz % 60)))
+
+	if tz >= 0 {
+		return "+" + format2(tz_hour) + ":" + format2(tz_min)
+	} else {
+		return "-" + format2(tz_hour) + ":" + format2(tz_min)
+	}
+}
+
+func toDTFromTime(x time.Time) []int {
+	hour, min, sec := x.Clock()
+	ts := make([]int, DT_LEN)
+	ts[OFFSET_YEAR] = x.Year()
+	ts[OFFSET_MONTH] = int(x.Month())
+	ts[OFFSET_DAY] = x.Day()
+	ts[OFFSET_HOUR] = hour
+	ts[OFFSET_MINUTE] = min
+	ts[OFFSET_SECOND] = sec
+	ts[OFFSET_NANOSECOND] = (int)(x.Nanosecond())
+	_, tz := x.Zone()
+	ts[OFFSET_TIMEZONE] = tz / 60
+	return ts
+}
+
+func toDTFromUnix(sec int64, nsec int64) []int {
+	return toDTFromTime(time.Unix(sec, nsec))
+}
+
+func toDTFromString(s string, dt []int) (dtype int, err error) {
+	defer func() {
+		if p := recover(); p != nil {
+			err = ECGO_INVALID_DATETIME_FORMAT.throw()
+		}
+	}()
+	date_s := ""
+	time_s := ""
+	nanos_s := ""
+	tz_s := ""
+	year := 0
+	month := 0
+	day := 0
+	hour := 0
+	minute := 0
+	second := 0
+	a_nanos := 0
+	firstDash := -1
+	secondDash := -1
+	firstColon := -1
+	secondColon := -1
+	period := -1
+	sign := 0
+	ownTz := INVALID_VALUE
+	dtype = -1
+
+	zeros := "000000000"
+
+	if s != "" && strings.TrimSpace(s) == "" {
+		return 0, ECGO_INVALID_DATETIME_FORMAT.throw()
+	}
+	s = strings.TrimSpace(s)
+
+	if strings.Index(s, "-") == 0 {
+		s = strings.TrimSpace(s[1:])
+		sign = 1
+	}
+
+	comps := strings.Split(s, " ")
+
+	switch len(comps) {
+	case 3:
+		date_s = comps[0]
+		time_s = comps[1]
+		tz_s = comps[2]
+		dtype = DATETIME_TZ
+
+	case 2:
+		if strings.Index(comps[0], ":") > 0 {
+			time_s = comps[0]
+			tz_s = comps[1]
+			dtype = TIME_TZ
+		} else {
+			date_s = comps[0]
+			time_s = comps[1]
+			dtype = DATETIME
+		}
+
+	case 1:
+		if strings.Index(comps[0], ":") > 0 {
+			time_s = comps[0]
+			dtype = TIME
+		} else {
+			date_s = comps[0]
+			dtype = DATE
+		}
+
+	default:
+		return 0, ECGO_INVALID_DATETIME_FORMAT.throw()
+	}
+
+	if date_s != "" {
+
+		firstDash = strings.Index(date_s, "-")
+		secondDash = strings.Index(date_s[firstDash+1:], "-")
+
+		if firstDash < 0 || secondDash < 0 {
+			firstDash = strings.Index(s, ".")
+			secondDash = strings.Index(date_s[firstDash+1:], ".")
+		}
+
+		if firstDash < 0 || secondDash < 0 {
+			firstDash = strings.Index(s, "/")
+			secondDash = strings.Index(date_s[firstDash+1:], "/")
+		}
+		if secondDash > 0 {
+			secondDash += firstDash + 1
+		}
+
+		if (firstDash > 0) && (secondDash > 0) && (secondDash < len(date_s)-1) {
+
+			if sign == 1 {
+				i, err := strconv.ParseInt(date_s[:firstDash], 10, 32)
+				if err != nil {
+					return 0, ECGO_INVALID_DATETIME_FORMAT.addDetailln(err.Error()).throw()
+				}
+				year = 0 - int(i) - 1900
+			} else {
+				i, err := strconv.ParseInt(date_s[:firstDash], 10, 32)
+				if err != nil {
+					return 0, ECGO_INVALID_DATETIME_FORMAT.addDetailln(err.Error()).throw()
+				}
+				year = int(i) - 1900
+			}
+
+			i, err := strconv.ParseInt(date_s[firstDash+1:secondDash], 10, 32)
+			if err != nil {
+				return 0, ECGO_INVALID_DATETIME_FORMAT.addDetailln(err.Error()).throw()
+			}
+			month = int(i) - 1
+
+			i, err = strconv.ParseInt(date_s[secondDash+1:], 10, 32)
+			if err != nil {
+				return 0, ECGO_INVALID_DATETIME_FORMAT.addDetailln(err.Error()).throw()
+			}
+			day = int(i)
+
+			if !checkDate(year+1900, month+1, day) {
+				return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
+			}
+		} else {
+			return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
+		}
+	}
+
+	if time_s != "" {
+		firstColon = strings.Index(time_s, ":")
+		secondColon = strings.Index(time_s[firstColon+1:], ":")
+		if secondColon > 0 {
+			secondColon += firstColon + 1
+		}
+
+		period = strings.Index(time_s[secondColon+1:], ".")
+		if period > 0 {
+			period += secondColon + 1
+		}
+
+		if (firstColon > 0) && (secondColon > 0) && (secondColon < len(time_s)-1) {
+			i, err := strconv.ParseInt(time_s[:firstColon], 10, 32)
+			if err != nil {
+				return 0, ECGO_INVALID_DATETIME_FORMAT.addDetailln(err.Error()).throw()
+			}
+			hour = int(i)
+
+			i, err = strconv.ParseInt(time_s[firstColon+1:secondColon], 10, 32)
+			if err != nil {
+				return 0, ECGO_INVALID_DATETIME_FORMAT.addDetailln(err.Error()).throw()
+			}
+			minute = int(i)
+
+			if period > 0 && period < len(time_s)-1 {
+				i, err = strconv.ParseInt(time_s[secondColon+1:period], 10, 32)
+				if err != nil {
+					return 0, ECGO_INVALID_DATETIME_FORMAT.addDetailln(err.Error()).throw()
+				}
+				second = int(i)
+
+				nanos_s = time_s[period+1:]
+				if len(nanos_s) > NANOSECOND_DIGITS {
+					return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
+				}
+				if !unicode.IsDigit(rune(nanos_s[0])) {
+					return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
+				}
+				nanos_s = nanos_s + zeros[0:NANOSECOND_DIGITS-len(nanos_s)]
+
+				i, err = strconv.ParseInt(nanos_s, 10, 32)
+				if err != nil {
+					return 0, ECGO_INVALID_DATETIME_FORMAT.addDetailln(err.Error()).throw()
+				}
+				a_nanos = int(i)
+			} else if period > 0 {
+				return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
+			} else {
+				i, err = strconv.ParseInt(time_s[secondColon+1:], 10, 32)
+				if err != nil {
+					return 0, ECGO_INVALID_DATETIME_FORMAT.addDetailln(err.Error()).throw()
+				}
+				second = int(i)
+			}
+
+			if hour >= 24 || hour < 0 || minute >= 60 || minute < 0 || second >= 60 || second < 0 {
+				return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
+			}
+		} else {
+			return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
+		}
+	}
+
+	if tz_s != "" {
+		neg := false
+		if strings.Index(tz_s, "-") == 0 {
+			neg = true
+		}
+
+		if strings.Index(tz_s, "-") == 0 || strings.Index(tz_s, "+") == 0 {
+			tz_s = strings.TrimSpace(tz_s[1:])
+		}
+
+		hm := strings.Split(tz_s, ":")
+		var tzh, tzm int16 = 0, 0
+		switch len(hm) {
+		case 2:
+			s, err := strconv.ParseInt(strings.TrimSpace(hm[0]), 10, 16)
+			if err != nil {
+				return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
+			}
+			tzh = int16(s)
+
+			s, err = strconv.ParseInt(strings.TrimSpace(hm[1]), 10, 16)
+			if err != nil {
+				return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
+			}
+			tzm = int16(s)
+		case 1:
+			s, err := strconv.ParseInt(strings.TrimSpace(hm[0]), 10, 16)
+			if err != nil {
+				return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
+			}
+			tzh = int16(s)
+		default:
+			return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
+		}
+
+		ownTz = int(tzh*60 + tzm)
+		if ownTz < 0 {
+			return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
+		}
+
+		if neg {
+			ownTz *= -1
+		}
+
+		if ownTz <= -13*60 || ownTz > 14*60 {
+			return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
+		}
+	}
+
+	dt[OFFSET_YEAR] = year + 1900
+	dt[OFFSET_MONTH] = month + 1
+	if day == 0 {
+		dt[OFFSET_DAY] = 1
+	} else {
+		dt[OFFSET_DAY] = day
+	}
+	dt[OFFSET_HOUR] = hour
+	dt[OFFSET_MINUTE] = minute
+	dt[OFFSET_SECOND] = second
+	dt[OFFSET_NANOSECOND] = a_nanos
+	dt[OFFSET_TIMEZONE] = int(ownTz)
+	return dtype, nil
+}
+
+func transformTZ(dt []int, defaultSrcTz int, destTz int) {
+	srcTz := defaultSrcTz
+
+	if srcTz != INVALID_VALUE && destTz != INVALID_VALUE && destTz != srcTz {
+		dt = addMinute(dt, destTz-srcTz)
+
+		dt[OFFSET_TIMEZONE] = destTz
+
+	}
+}
+
+func encode(dt []int, column column, lTz int, dTz int) ([]byte, error) {
+	if dt[OFFSET_TIMEZONE] != INVALID_VALUE {
+		transformTZ(dt, dt[OFFSET_TIMEZONE], lTz)
+	}
+
+	if column.mask == MASK_LOCAL_DATETIME {
+		transformTZ(dt, dt[OFFSET_TIMEZONE], dTz)
+	}
+
+	if dt[OFFSET_YEAR] < -4712 || dt[OFFSET_YEAR] > 9999 {
+		return nil, ECGO_DATETIME_OVERFLOW.throw()
+	}
+
+	year := dt[OFFSET_YEAR]
+
+	month := dt[OFFSET_MONTH]
+
+	day := dt[OFFSET_DAY]
+
+	hour := dt[OFFSET_HOUR]
+
+	min := dt[OFFSET_MINUTE]
+
+	sec := dt[OFFSET_SECOND]
+
+	msec := dt[OFFSET_NANOSECOND]
+
+	var tz int
+
+	if dt[OFFSET_TIMEZONE] == INVALID_VALUE {
+		tz = dTz
+	} else {
+		tz = dt[OFFSET_TIMEZONE]
+	}
+
+	var ret []byte
+
+	if column.colType == DATE {
+		ret = make([]byte, 3)
+
+		ret[0] = (byte)(year & 0xFF)
+
+		if year >= 0 {
+			ret[1] = (byte)((year >> 8) | ((month & 0x01) << 7))
+		} else {
+			ret[1] = (byte)((year >> 8) & (((month & 0x01) << 7) | 0x7f))
+		}
+
+		ret[2] = (byte)(((month & 0x0E) >> 1) | (day << 3))
+	} else if column.colType == DATETIME {
+		msec /= 1000
+		ret = make([]byte, 8)
+
+		ret[0] = (byte)(year & 0xFF)
+
+		if year >= 0 {
+			ret[1] = (byte)((year >> 8) | ((month & 0x01) << 7))
+		} else {
+			ret[1] = (byte)((year >> 8) & (((month & 0x01) << 7) | 0x7f))
+		}
+
+		ret[2] = (byte)(((month & 0x0E) >> 1) | (day << 3))
+
+		ret[3] = (byte)(hour | ((min & 0x07) << 5))
+
+		ret[4] = (byte)(((min & 0x38) >> 3) | ((sec & 0x1F) << 3))
+
+		ret[5] = (byte)(((sec & 0x20) >> 5) | ((msec & 0x7F) << 1))
+
+		ret[6] = (byte)((msec >> 7) & 0xFF)
+
+		ret[7] = (byte)((msec >> 15) & 0xFF)
+	} else if column.colType == DATETIME2 {
+		ret = make([]byte, 9)
+
+		ret[0] = (byte)(year & 0xFF)
+
+		if year >= 0 {
+			ret[1] = (byte)((year >> 8) | ((month & 0x01) << 7))
+		} else {
+			ret[1] = (byte)((year >> 8) & (((month & 0x01) << 7) | 0x7f))
+		}
+
+		ret[2] = (byte)(((month & 0x0E) >> 1) | (day << 3))
+
+		ret[3] = (byte)(hour | ((min & 0x07) << 5))
+
+		ret[4] = (byte)(((min & 0x38) >> 3) | ((sec & 0x1F) << 3))
+
+		ret[5] = (byte)(((sec & 0x20) >> 5) | ((msec & 0x7F) << 1))
+
+		ret[6] = (byte)((msec >> 7) & 0xFF)
+
+		ret[7] = (byte)((msec >> 15) & 0xFF)
+
+		ret[8] = (byte)((msec >> 23) & 0xFF)
+	} else if column.colType == DATETIME_TZ {
+		msec /= 1000
+		ret = make([]byte, 10)
+
+		ret[0] = (byte)(year & 0xFF)
+
+		if year >= 0 {
+			ret[1] = (byte)((year >> 8) | ((month & 0x01) << 7))
+		} else {
+			ret[1] = (byte)((year >> 8) & (((month & 0x01) << 7) | 0x7f))
+		}
+
+		ret[2] = (byte)(((month & 0x0E) >> 1) | (day << 3))
+
+		ret[3] = (byte)(hour | ((min & 0x07) << 5))
+
+		ret[4] = (byte)(((min & 0x38) >> 3) | ((sec & 0x1F) << 3))
+
+		ret[5] = (byte)(((sec & 0x20) >> 5) | ((msec & 0x7F) << 1))
+
+		ret[6] = (byte)((msec >> 7) & 0xFF)
+
+		ret[7] = (byte)((msec >> 15) & 0xFF)
+
+		Dm_build_1.Dm_build_12(ret, 8, int16(tz))
+	} else if column.colType == DATETIME2_TZ {
+		ret = make([]byte, 11)
+
+		ret[0] = (byte)(year & 0xFF)
+
+		if year >= 0 {
+			ret[1] = (byte)((year >> 8) | ((month & 0x01) << 7))
+		} else {
+			ret[1] = (byte)((year >> 8) & (((month & 0x01) << 7) | 0x7f))
+		}
+
+		ret[2] = (byte)(((month & 0x0E) >> 1) | (day << 3))
+
+		ret[3] = (byte)(hour | ((min & 0x07) << 5))
+
+		ret[4] = (byte)(((min & 0x38) >> 3) | ((sec & 0x1F) << 3))
+
+		ret[5] = (byte)(((sec & 0x20) >> 5) | ((msec & 0x7F) << 1))
+
+		ret[6] = (byte)((msec >> 7) & 0xFF)
+
+		ret[7] = (byte)((msec >> 15) & 0xFF)
+
+		ret[8] = (byte)((msec >> 23) & 0xFF)
+
+		Dm_build_1.Dm_build_12(ret, 8, int16(tz))
+	} else if column.colType == TIME {
+		msec /= 1000
+		ret = make([]byte, 5)
+
+		ret[0] = (byte)(hour | ((min & 0x07) << 5))
+
+		ret[1] = (byte)(((min & 0x38) >> 3) | ((sec & 0x1F) << 3))
+
+		ret[2] = (byte)(((sec & 0x20) >> 5) | ((msec & 0x7F) << 1))
+
+		ret[3] = (byte)((msec >> 7) & 0xFF)
+
+		ret[4] = (byte)((msec >> 15) & 0xFF)
+	} else if column.colType == TIME_TZ {
+		msec /= 1000
+		ret = make([]byte, 7)
+
+		ret[0] = (byte)(hour | ((min & 0x07) << 5))
+
+		ret[1] = (byte)(((min & 0x38) >> 3) | ((sec & 0x1F) << 3))
+
+		ret[2] = (byte)(((sec & 0x20) >> 5) | ((msec & 0x7F) << 1))
+
+		ret[3] = (byte)((msec >> 7) & 0xFF)
+
+		ret[4] = (byte)((msec >> 15) & 0xFF)
+
+		Dm_build_1.Dm_build_12(ret, 5, int16(tz))
+	}
+
+	return ret, nil
+}
+
+func toDate(x int64, column column, conn DmConnection) ([]byte, error) {
+	switch column.colType {
+	case DATETIME, DATETIME2:
+		if x > 2958463*24*60*60 {
+			return nil, ECGO_DATETIME_OVERFLOW.throw()
+		}
+
+		dt := toDTFromUnix(x-Seconds_1900_1970, 0)
+		return encode(dt, column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
+
+	case TIME:
+		dt := toDTFromUnix(x, 0)
+		return encode(dt, column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
+
+	case DATE:
+		if x > 2958463 {
+			return nil, ECGO_DATETIME_OVERFLOW.throw()
+		}
+
+		dt := toDTFromUnix(x*24*60*60-Seconds_1900_1970, 0)
+		if dt[OFFSET_YEAR] < -4712 || dt[OFFSET_YEAR] > 9999 {
+			return nil, ECGO_DATETIME_OVERFLOW.throw()
+		}
+		return encode(dt, column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
+
+	default:
+		return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+	}
+}
+
+func checkDate(year int, month int, day int) bool {
+	if year > 9999 || year < -4712 || month > 12 || month < 1 {
+		return false
+	}
+
+	monthDays := getDaysOfMonth(year, month)
+	if day > monthDays || day < 1 {
+		return false
+	}
+	return true
+}
+
+func getDaysOfMonth(year int, month int) int {
+	switch month {
+	case 1, 3, 5, 7, 8, 10, 12:
+		return 31
+	case 4, 6, 9, 11:
+		return 30
+	case 2:
+		if isLeapYear(year) {
+			return 29
+		}
+		return 28
+	default:
+		return 0
+	}
+}
+
+func isLeapYear(year int) bool {
+	return (year%4 == 0 && year%100 != 0) || year%400 == 0
+}
+
+func addYear(dt []int, n int) []int {
+	dt[OFFSET_YEAR] += n
+	return dt
+}
+
+func addMonth(dt []int, n int) []int {
+	month := dt[OFFSET_MONTH] + n
+	addYearValue := month / 12
+	if month %= 12; month < 1 {
+		month += 12
+		addYearValue--
+	}
+
+	daysOfMonth := getDaysOfMonth(dt[OFFSET_YEAR], month)
+	if dt[OFFSET_DAY] > daysOfMonth {
+		dt[OFFSET_DAY] = daysOfMonth
+	}
+
+	dt[OFFSET_MONTH] = month
+	addYear(dt, addYearValue)
+	return dt
+}
+
+func addDay(dt []int, n int) []int {
+	tmp := dt[OFFSET_DAY] + n
+	monthDays := 0
+	monthDays = getDaysOfMonth(dt[OFFSET_YEAR], dt[OFFSET_MONTH])
+	for tmp > monthDays || tmp <= 0 {
+		if tmp > monthDays {
+			addMonth(dt, 1)
+			tmp -= monthDays
+		} else {
+			addMonth(dt, -1)
+			tmp += monthDays
+		}
+	}
+	dt[OFFSET_DAY] = tmp
+	return dt
+}
+
+func addHour(dt []int, n int) []int {
+	hour := dt[OFFSET_HOUR] + n
+	addDayValue := hour / 24
+	if hour %= 24; hour < 0 {
+		hour += 24
+		addDayValue--
+	}
+
+	dt[OFFSET_HOUR] = hour
+	addDay(dt, addDayValue)
+	return dt
+}
+
+func addMinute(dt []int, n int) []int {
+	minute := dt[OFFSET_MINUTE] + n
+	addHourValue := minute / 60
+	if minute %= 60; minute < 0 {
+		minute += 60
+		addHourValue--
+	}
+
+	dt[OFFSET_MINUTE] = minute
+	addHour(dt, addHourValue)
+	return dt
+}

+ 917 - 0
i.go

@@ -0,0 +1,917 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"strconv"
+	"time"
+
+	"gitee.com/chunanyong/dm/util"
+)
+
+var DB2G db2g
+
+type db2g struct {
+}
+
+func (DB2G db2g) processVarchar2(bytes []byte, prec int) []byte {
+	rbytes := make([]byte, prec)
+	copy(rbytes[:len(bytes)], bytes[:])
+	for i := len(bytes); i < len(rbytes); i++ {
+		rbytes[i] = ' '
+	}
+	return rbytes
+}
+
+func (DB2G db2g) charToString(bytes []byte, column *column, conn *DmConnection) string {
+	if column.colType == VARCHAR2 {
+		bytes = DB2G.processVarchar2(bytes, int(column.prec))
+	} else if column.colType == CLOB {
+		clob := newClobFromDB(bytes, conn, column, true)
+		clobLen, _ := clob.GetLength()
+		clobStr, _ := clob.getSubString(1, int32(clobLen))
+		return clobStr
+	}
+	return Dm_build_1.Dm_build_254(bytes, conn.serverEncoding, conn)
+}
+
+func (DB2G db2g) charToFloat64(bytes []byte, column *column, conn *DmConnection) (float64, error) {
+	str := DB2G.charToString(bytes, column, conn)
+	val, err := strconv.ParseFloat(str, 64)
+	if err != nil {
+		return 0, ECGO_DATA_CONVERTION_ERROR.throw()
+	}
+
+	return val, nil
+}
+
+func (DB2G db2g) charToDeciaml(bytes []byte, column *column, conn *DmConnection) (*DmDecimal, error) {
+	str := DB2G.charToString(bytes, column, conn)
+	return NewDecimalFromString(str)
+}
+
+func (DB2G db2g) BinaryToInt64(bytes []byte, column *column, conn *DmConnection) (int64, error) {
+	if column.colType == BLOB {
+		blob := newBlobFromDB(bytes, conn, column, true)
+		blobLen, err := blob.GetLength()
+		if err != nil {
+			return 0, err
+		}
+		bytes, err = blob.getBytes(1, int32(blobLen))
+		if err != nil {
+			return 0, err
+		}
+	}
+	var n, b int64 = 0, 0
+
+	startIndex := 0
+	var length int
+	if len(bytes) > 8 {
+		length = 8
+		for j := 0; j < len(bytes)-8; j++ {
+			if bytes[j] != 0 {
+				return 0, ECGO_DATA_CONVERTION_ERROR.throw()
+			}
+
+			startIndex = len(bytes) - 8
+			length = 8
+		}
+	} else {
+		length = len(bytes)
+	}
+
+	for j := startIndex; j < startIndex+length; j++ {
+		b = int64(0xff & bytes[j])
+		n = b | (n << 8)
+	}
+
+	return n, nil
+}
+
+func (DB2G db2g) decToDecimal(bytes []byte, prec int, scale int, compatibleOracle bool) (*DmDecimal, error) {
+
+	if compatibleOracle {
+		prec = -1
+		scale = -1
+	}
+	return newDecimal(bytes, prec, scale)
+}
+
+func (DB2G db2g) toBytes(bytes []byte, column *column, conn *DmConnection) ([]byte, error) {
+	retBytes := Dm_build_1.Dm_build_152(bytes, 0, len(bytes))
+	switch column.colType {
+	case CLOB:
+		clob := newClobFromDB(retBytes, conn, column, true)
+		str, err := clob.getSubString(1, int32(clob.length))
+		if err != nil {
+			return nil, err
+		}
+
+		return Dm_build_1.Dm_build_217(str, conn.getServerEncoding(), conn), nil
+	case BLOB:
+		blob := newBlobFromDB(retBytes, conn, column, true)
+		bs, err := blob.getBytes(1, int32(blob.length))
+		if err != nil {
+			return nil, err
+		}
+
+		return bs, nil
+	}
+	return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+}
+
+func (DB2G db2g) toString(bytes []byte, column *column, conn *DmConnection) string {
+	switch column.colType {
+	case CHAR, VARCHAR, VARCHAR2:
+		return DB2G.charToString(bytes, column, conn)
+	case BIT, BOOLEAN, TINYINT:
+		return strconv.FormatInt(int64(bytes[0]), 10)
+	case SMALLINT:
+		return strconv.FormatInt(int64(Dm_build_1.Dm_build_225(bytes)), 10)
+	case INT:
+		return strconv.FormatInt(int64(Dm_build_1.Dm_build_228(bytes)), 10)
+	case BIGINT:
+		return strconv.FormatInt(int64(Dm_build_1.Dm_build_231(bytes)), 10)
+	case REAL:
+		return strconv.FormatFloat(float64(Dm_build_1.Dm_build_234(bytes)), 'f', -1, 32)
+	case DOUBLE:
+		return strconv.FormatFloat(float64(Dm_build_1.Dm_build_237(bytes)), 'f', -1, 64)
+	case DECIMAL:
+
+	case BINARY, VARBINARY:
+		util.StringUtil.BytesToHexString(bytes, false)
+	case BLOB:
+
+	case CLOB:
+
+	case DATE:
+		dt := decode(bytes, column.isBdta, *column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
+		if conn.FormatDate != "" {
+			return dtToStringByOracleFormat(dt, conn.FormatDate, column.scale, int(conn.OracleDateLanguage))
+		}
+	case TIME:
+		dt := decode(bytes, column.isBdta, *column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
+		if conn.FormatTime != "" {
+			return dtToStringByOracleFormat(dt, conn.FormatTime, column.scale, int(conn.OracleDateLanguage))
+		}
+	case DATETIME, DATETIME2:
+		dt := decode(bytes, column.isBdta, *column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
+		if conn.FormatTimestamp != "" {
+			return dtToStringByOracleFormat(dt, conn.FormatTimestamp, column.scale, int(conn.OracleDateLanguage))
+		}
+	case TIME_TZ:
+		dt := decode(bytes, column.isBdta, *column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
+		if conn.FormatTimeTZ != "" {
+			return dtToStringByOracleFormat(dt, conn.FormatTimeTZ, column.scale, int(conn.OracleDateLanguage))
+		}
+	case DATETIME_TZ, DATETIME2_TZ:
+		dt := decode(bytes, column.isBdta, *column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
+		if conn.FormatTimestampTZ != "" {
+			return dtToStringByOracleFormat(dt, conn.FormatTimestampTZ, column.scale, int(conn.OracleDateLanguage))
+		}
+	case INTERVAL_DT:
+		return newDmIntervalDTByBytes(bytes).String()
+	case INTERVAL_YM:
+		return newDmIntervalYMByBytes(bytes).String()
+	case ARRAY:
+
+	case SARRAY:
+
+	case CLASS:
+
+	case PLTYPE_RECORD:
+
+	}
+	return ""
+}
+
+func (DB2G db2g) toBool(bytes []byte, column *column, conn *DmConnection) (bool, error) {
+	switch column.colType {
+	case BIT, BOOLEAN, TINYINT:
+		return bytes[0] != 0, nil
+	case SMALLINT:
+		return Dm_build_1.Dm_build_98(bytes, 0) != 0, nil
+	case INT:
+		return Dm_build_1.Dm_build_103(bytes, 0) != 0, nil
+	case BIGINT:
+		return Dm_build_1.Dm_build_108(bytes, 0) != 0, nil
+	case REAL:
+		return Dm_build_1.Dm_build_113(bytes, 0) != 0, nil
+	case DOUBLE:
+		return Dm_build_1.Dm_build_117(bytes, 0) != 0, nil
+	case DECIMAL:
+
+	case CHAR, VARCHAR, VARCHAR2, CLOB:
+		return G2DB.toBool(DB2G.charToString(bytes, column, conn))
+	}
+
+	return false, ECGO_DATA_CONVERTION_ERROR.throw()
+}
+
+func (DB2G db2g) toByte(bytes []byte, column *column, conn *DmConnection) (byte, error) {
+	switch column.colType {
+	case BIT, BOOLEAN, TINYINT:
+
+		if bytes == nil || len(bytes) == 0 {
+			return 0, nil
+		} else {
+			return bytes[0], nil
+		}
+	case SMALLINT:
+		tval := Dm_build_1.Dm_build_98(bytes, 0)
+		if tval < int16(BYTE_MIN) || tval > int16(BYTE_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return byte(tval), nil
+	case INT:
+		tval := Dm_build_1.Dm_build_103(bytes, 0)
+		if tval < int32(BYTE_MIN) || tval > int32(BYTE_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return byte(tval), nil
+	case BIGINT:
+		tval := Dm_build_1.Dm_build_108(bytes, 0)
+		if tval < int64(BYTE_MIN) || tval > int64(BYTE_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return byte(tval), nil
+	case REAL:
+		tval := Dm_build_1.Dm_build_113(bytes, 0)
+		if tval < float32(BYTE_MIN) || tval > float32(BYTE_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return byte(tval), nil
+	case DOUBLE:
+		tval := Dm_build_1.Dm_build_117(bytes, 0)
+		if tval < float64(BYTE_MIN) || tval > float64(BYTE_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return byte(tval), nil
+	case DECIMAL:
+
+	case CHAR, VARCHAR, VARCHAR2, CLOB:
+		tval, err := DB2G.charToFloat64(bytes, column, conn)
+		if err != nil {
+			return 0, err
+		}
+
+		if tval < float64(BYTE_MIN) || tval > float64(BYTE_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return byte(tval), nil
+	case BINARY, VARBINARY, BLOB:
+		{
+			tval, err := DB2G.BinaryToInt64(bytes, column, conn)
+			if err != nil {
+				return 0, err
+			}
+
+			if tval < int64(BYTE_MIN) || tval > int64(BYTE_MAX) {
+				return 0, ECGO_DATA_OVERFLOW.throw()
+			}
+			return byte(tval), nil
+		}
+	}
+
+	return 0, ECGO_DATA_CONVERTION_ERROR.throw()
+}
+
+func (DB2G db2g) toInt8(bytes []byte, column *column, conn *DmConnection) (int8, error) {
+	switch column.colType {
+	case BIT, BOOLEAN, TINYINT:
+		if bytes == nil || len(bytes) == 0 {
+			return 0, nil
+		}
+
+		return int8(bytes[0]), nil
+	case SMALLINT:
+		tval := Dm_build_1.Dm_build_98(bytes, 0)
+		if tval < int16(INT8_MIN) || tval < int16(INT8_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return int8(tval), nil
+	case INT:
+
+		tval := Dm_build_1.Dm_build_103(bytes, 0)
+		if tval < int32(INT8_MIN) || tval > int32(INT8_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return int8(tval), nil
+	case BIGINT:
+		tval := Dm_build_1.Dm_build_108(bytes, 0)
+		if tval < int64(INT8_MIN) || tval > int64(INT8_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return int8(tval), nil
+	case REAL:
+		tval := Dm_build_1.Dm_build_113(bytes, 0)
+		if tval < float32(INT8_MIN) || tval > float32(INT8_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return int8(tval), nil
+	case DOUBLE:
+		tval := Dm_build_1.Dm_build_117(bytes, 0)
+		if tval < float64(INT8_MIN) || tval > float64(INT8_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return int8(tval), nil
+	case DECIMAL:
+
+	case CHAR, VARCHAR, VARCHAR2, CLOB:
+		tval, err := DB2G.charToFloat64(bytes, column, conn)
+		if err != nil {
+			return 0, err
+		}
+
+		if tval < float64(INT8_MIN) || tval > float64(INT8_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return int8(tval), nil
+	case BINARY, VARBINARY, BLOB:
+		{
+			tval, err := DB2G.BinaryToInt64(bytes, column, conn)
+			if err != nil {
+				return 0, err
+			}
+
+			if tval < int64(INT8_MIN) || tval > int64(INT8_MAX) {
+				return 0, ECGO_DATA_OVERFLOW.throw()
+			}
+			return int8(tval), nil
+		}
+	}
+
+	return 0, ECGO_DATA_CONVERTION_ERROR.throw()
+}
+
+func (DB2G db2g) toInt16(bytes []byte, column *column, conn *DmConnection) (int16, error) {
+	switch column.colType {
+	case BIT, BOOLEAN, TINYINT:
+		if bytes == nil || len(bytes) == 0 {
+			return 0, nil
+		}
+
+		return int16(bytes[0]), nil
+	case SMALLINT:
+		return Dm_build_1.Dm_build_98(bytes, 0), nil
+	case INT:
+
+		tval := Dm_build_1.Dm_build_103(bytes, 0)
+		if tval < int32(INT16_MIN) || tval > int32(INT16_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return int16(tval), nil
+	case BIGINT:
+		tval := Dm_build_1.Dm_build_108(bytes, 0)
+		if tval < int64(INT16_MIN) || tval > int64(INT16_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return int16(tval), nil
+	case REAL:
+		tval := Dm_build_1.Dm_build_113(bytes, 0)
+		if tval < float32(INT16_MIN) || tval > float32(INT16_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return int16(tval), nil
+	case DOUBLE:
+		tval := Dm_build_1.Dm_build_117(bytes, 0)
+		if tval < float64(INT16_MIN) || tval > float64(INT16_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return int16(tval), nil
+	case DECIMAL:
+
+	case CHAR, VARCHAR, VARCHAR2, CLOB:
+		tval, err := DB2G.charToFloat64(bytes, column, conn)
+		if err != nil {
+			return 0, err
+		}
+
+		if tval < float64(INT16_MIN) || tval > float64(INT16_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return int16(tval), nil
+	case BINARY, VARBINARY, BLOB:
+		{
+			tval, err := DB2G.BinaryToInt64(bytes, column, conn)
+			if err != nil {
+				return 0, err
+			}
+
+			if tval < int64(INT16_MIN) || tval > int64(INT16_MAX) {
+				return 0, ECGO_DATA_OVERFLOW.throw()
+			}
+			return int16(tval), nil
+		}
+	}
+
+	return 0, ECGO_DATA_CONVERTION_ERROR.throw()
+}
+
+func (DB2G db2g) toUInt16(bytes []byte, column *column, conn *DmConnection) (uint16, error) {
+	switch column.colType {
+	case BIT, BOOLEAN, TINYINT:
+		if bytes == nil || len(bytes) == 0 {
+			return 0, nil
+		}
+
+		return uint16(bytes[0]), nil
+	case SMALLINT:
+		return uint16(Dm_build_1.Dm_build_98(bytes, 0)), nil
+	case INT:
+		tval := Dm_build_1.Dm_build_103(bytes, 0)
+		if tval < int32(UINT16_MIN) || tval > int32(UINT16_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return uint16(tval), nil
+	case BIGINT:
+		tval := Dm_build_1.Dm_build_108(bytes, 0)
+		if tval < int64(UINT16_MIN) || tval > int64(UINT16_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return uint16(tval), nil
+	case REAL:
+		tval := Dm_build_1.Dm_build_113(bytes, 0)
+		if tval < float32(UINT16_MIN) || tval > float32(UINT16_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return uint16(tval), nil
+	case DOUBLE:
+		tval := Dm_build_1.Dm_build_117(bytes, 0)
+		if tval < float64(UINT16_MIN) || tval > float64(UINT16_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return uint16(tval), nil
+	case DECIMAL:
+
+	case CHAR, VARCHAR, VARCHAR2, CLOB:
+		tval, err := DB2G.charToFloat64(bytes, column, conn)
+		if err != nil {
+			return 0, err
+		}
+
+		if tval < float64(UINT16_MIN) || tval > float64(UINT16_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return uint16(tval), nil
+	case BINARY, VARBINARY, BLOB:
+		{
+			tval, err := DB2G.BinaryToInt64(bytes, column, conn)
+			if err != nil {
+				return 0, err
+			}
+
+			if tval < int64(UINT16_MIN) || tval > int64(UINT16_MAX) {
+				return 0, ECGO_DATA_OVERFLOW.throw()
+			}
+			return uint16(tval), nil
+		}
+	}
+
+	return 0, ECGO_DATA_CONVERTION_ERROR.throw()
+}
+
+func (DB2G db2g) toInt32(bytes []byte, column *column, conn *DmConnection) (int32, error) {
+	switch column.colType {
+	case BIT, BOOLEAN, TINYINT:
+		if bytes == nil || len(bytes) == 0 {
+			return 0, nil
+		}
+
+		return int32(bytes[0]), nil
+	case SMALLINT:
+		return int32(Dm_build_1.Dm_build_98(bytes, 0)), nil
+	case INT:
+		return Dm_build_1.Dm_build_103(bytes, 0), nil
+	case BIGINT:
+		tval := Dm_build_1.Dm_build_108(bytes, 0)
+		if tval < int64(INT32_MIN) || tval > int64(INT32_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return int32(tval), nil
+	case REAL:
+		tval := Dm_build_1.Dm_build_113(bytes, 0)
+		if tval < float32(INT32_MIN) || tval > float32(INT32_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return int32(tval), nil
+	case DOUBLE:
+		tval := Dm_build_1.Dm_build_117(bytes, 0)
+		if tval < float64(INT32_MIN) || tval > float64(INT32_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return int32(tval), nil
+	case DECIMAL:
+
+	case CHAR, VARCHAR, VARCHAR2, CLOB:
+		tval, err := DB2G.charToFloat64(bytes, column, conn)
+		if err != nil {
+			return 0, err
+		}
+
+		if tval < float64(INT32_MIN) || tval > float64(INT32_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return int32(tval), nil
+	case BINARY, VARBINARY, BLOB:
+		{
+			tval, err := DB2G.BinaryToInt64(bytes, column, conn)
+			if err != nil {
+				return 0, err
+			}
+
+			if tval < int64(INT32_MIN) || tval > int64(INT32_MAX) {
+				return 0, ECGO_DATA_OVERFLOW.throw()
+			}
+			return int32(tval), nil
+		}
+	}
+
+	return 0, ECGO_DATA_CONVERTION_ERROR.throw()
+}
+
+func (DB2G db2g) toUInt32(bytes []byte, column *column, conn *DmConnection) (uint32, error) {
+	switch column.colType {
+	case BIT, BOOLEAN, TINYINT:
+		if bytes == nil || len(bytes) == 0 {
+			return 0, nil
+		}
+
+		return uint32(bytes[0]), nil
+	case SMALLINT:
+		return uint32(Dm_build_1.Dm_build_98(bytes, 0)), nil
+	case INT:
+		return uint32(Dm_build_1.Dm_build_103(bytes, 0)), nil
+	case BIGINT:
+		tval := Dm_build_1.Dm_build_108(bytes, 0)
+		if tval < int64(UINT32_MIN) || tval > int64(UINT32_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return uint32(tval), nil
+	case REAL:
+		tval := Dm_build_1.Dm_build_113(bytes, 0)
+		if tval < float32(UINT32_MIN) || tval > float32(UINT32_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return uint32(tval), nil
+	case DOUBLE:
+		tval := Dm_build_1.Dm_build_117(bytes, 0)
+		if tval < float64(UINT32_MIN) || tval > float64(UINT32_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return uint32(tval), nil
+	case DECIMAL:
+
+	case CHAR, VARCHAR, VARCHAR2, CLOB:
+		tval, err := DB2G.charToFloat64(bytes, column, conn)
+		if err != nil {
+			return 0, err
+		}
+
+		if tval < float64(UINT32_MIN) || tval > float64(UINT32_MAX) {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return uint32(tval), nil
+	case BINARY, VARBINARY, BLOB:
+		{
+			tval, err := DB2G.BinaryToInt64(bytes, column, conn)
+			if err != nil {
+				return 0, err
+			}
+
+			if tval < int64(UINT32_MIN) || tval > int64(UINT32_MAX) {
+				return 0, ECGO_DATA_OVERFLOW.throw()
+			}
+			return uint32(tval), nil
+		}
+	}
+
+	return 0, ECGO_DATA_CONVERTION_ERROR.throw()
+}
+
+func (DB2G db2g) toInt64(bytes []byte, column *column, conn *DmConnection) (int64, error) {
+	switch column.colType {
+	case BOOLEAN, BIT, TINYINT:
+		if bytes == nil || len(bytes) == 0 {
+			return int64(0), nil
+		} else {
+			return int64(bytes[0]), nil
+		}
+	case SMALLINT:
+		return int64(Dm_build_1.Dm_build_225(bytes)), nil
+	case INT:
+		return int64(Dm_build_1.Dm_build_228(bytes)), nil
+	case BIGINT:
+		return int64(Dm_build_1.Dm_build_231(bytes)), nil
+	case REAL:
+		return int64(Dm_build_1.Dm_build_234(bytes)), nil
+	case DOUBLE:
+		return int64(Dm_build_1.Dm_build_237(bytes)), nil
+
+	case CHAR, VARCHAR2, VARCHAR, CLOB:
+		tval, err := DB2G.charToFloat64(bytes, column, conn)
+		if err != nil {
+			return 0, err
+		}
+
+		if int64(tval) < INT64_MIN || int64(tval) > INT64_MAX {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return int64(tval), nil
+	case BINARY, VARBINARY, BLOB:
+		tval, err := DB2G.BinaryToInt64(bytes, column, conn)
+		if err != nil {
+			return 0, err
+		}
+
+		return tval, nil
+	}
+	return 0, ECGO_DATA_CONVERTION_ERROR.throw()
+}
+
+func (DB2G db2g) toUInt64(bytes []byte, column *column, conn *DmConnection) (uint64, error) {
+	switch column.colType {
+	case BOOLEAN, BIT, TINYINT:
+		if bytes == nil || len(bytes) == 0 {
+			return uint64(0), nil
+		} else {
+			return uint64(bytes[0]), nil
+		}
+	case SMALLINT:
+		return uint64(Dm_build_1.Dm_build_225(bytes)), nil
+	case INT:
+		return uint64(Dm_build_1.Dm_build_228(bytes)), nil
+	case BIGINT:
+		return uint64(Dm_build_1.Dm_build_231(bytes)), nil
+	case REAL:
+		return uint64(Dm_build_1.Dm_build_234(bytes)), nil
+	case DOUBLE:
+		return uint64(Dm_build_1.Dm_build_237(bytes)), nil
+
+	case CHAR, VARCHAR2, VARCHAR, CLOB:
+		tval, err := DB2G.charToFloat64(bytes, column, conn)
+		if err != nil {
+			return 0, err
+		}
+
+		if uint64(tval) < UINT64_MIN || uint64(tval) > UINT64_MAX {
+			return 0, ECGO_DATA_OVERFLOW.throw()
+		}
+		return uint64(tval), nil
+	case BINARY, VARBINARY, BLOB:
+		tval, err := DB2G.BinaryToInt64(bytes, column, conn)
+		if err != nil {
+			return 0, err
+		}
+
+		return uint64(tval), nil
+	}
+	return 0, ECGO_DATA_CONVERTION_ERROR.throw()
+}
+
+func (DB2G db2g) toInt(bytes []byte, column *column, conn *DmConnection) (int, error) {
+	if strconv.IntSize == 32 {
+		tmp, err := DB2G.toInt32(bytes, column, conn)
+		return int(tmp), err
+	} else {
+		tmp, err := DB2G.toInt64(bytes, column, conn)
+		return int(tmp), err
+	}
+}
+
+func (DB2G db2g) toUInt(bytes []byte, column *column, conn *DmConnection) (uint, error) {
+	if strconv.IntSize == 32 {
+		tmp, err := DB2G.toUInt32(bytes, column, conn)
+		return uint(tmp), err
+	} else {
+		tmp, err := DB2G.toUInt64(bytes, column, conn)
+		return uint(tmp), err
+	}
+}
+
+func (DB2G db2g) toFloat32(bytes []byte, column *column, conn *DmConnection) (float32, error) {
+	switch column.colType {
+	case BIT, BOOLEAN, TINYINT:
+		if bytes == nil || len(bytes) == 0 {
+			return 0, nil
+		}
+		return float32(bytes[0]), nil
+	case SMALLINT:
+		return float32(Dm_build_1.Dm_build_98(bytes, 0)), nil
+	case INT:
+		return float32(Dm_build_1.Dm_build_103(bytes, 0)), nil
+	case BIGINT:
+		return float32(Dm_build_1.Dm_build_108(bytes, 0)), nil
+	case REAL:
+		return Dm_build_1.Dm_build_113(bytes, 0), nil
+	case DOUBLE:
+		dval := Dm_build_1.Dm_build_117(bytes, 0)
+		return float32(dval), nil
+	case DECIMAL:
+		dval, err := DB2G.decToDecimal(bytes, int(column.prec), int(column.scale), conn.CompatibleOracle())
+		if err != nil {
+			return 0, err
+		}
+		return float32(dval.ToFloat64()), nil
+	case CHAR, VARCHAR2, VARCHAR, CLOB:
+		dval, err := DB2G.charToDeciaml(bytes, column, conn)
+		if err != nil {
+			return 0, err
+		}
+		return float32(dval.ToFloat64()), nil
+	}
+	return 0, ECGO_DATA_CONVERTION_ERROR.throw()
+}
+
+func (DB2G db2g) toFloat64(bytes []byte, column *column, conn *DmConnection) (float64, error) {
+	switch column.colType {
+	case BIT, BOOLEAN, TINYINT:
+		if bytes == nil || len(bytes) == 0 {
+			return 0, nil
+		}
+		return float64(bytes[0]), nil
+	case SMALLINT:
+		return float64(Dm_build_1.Dm_build_98(bytes, 0)), nil
+	case INT:
+		return float64(Dm_build_1.Dm_build_103(bytes, 0)), nil
+	case BIGINT:
+		return float64(Dm_build_1.Dm_build_108(bytes, 0)), nil
+	case REAL:
+		return float64(Dm_build_1.Dm_build_113(bytes, 0)), nil
+	case DOUBLE:
+		return Dm_build_1.Dm_build_117(bytes, 0), nil
+	case DECIMAL:
+		dval, err := DB2G.decToDecimal(bytes, int(column.prec), int(column.scale), conn.CompatibleOracle())
+		if err != nil {
+			return 0, err
+		}
+		return dval.ToFloat64(), nil
+	case CHAR, VARCHAR2, VARCHAR, CLOB:
+		dval, err := DB2G.charToDeciaml(bytes, column, conn)
+		if err != nil {
+			return 0, err
+		}
+		return dval.ToFloat64(), nil
+	}
+
+	return 0, ECGO_DATA_CONVERTION_ERROR.throw()
+}
+
+func (DB2G db2g) toDmBlob(value []byte, column *column, conn *DmConnection) *DmBlob {
+
+	switch column.colType {
+	case BLOB:
+		return newBlobFromDB(value, conn, column, conn.lobFetchAll())
+	default:
+		return newBlobOfLocal(value, conn)
+	}
+}
+
+func (DB2G db2g) toDmClob(value []byte, conn *DmConnection, column *column) *DmClob {
+
+	switch column.colType {
+	case CLOB:
+		return newClobFromDB(value, conn, column, conn.lobFetchAll())
+	default:
+		return newClobOfLocal(DB2G.toString(value, column, conn), conn)
+	}
+}
+
+func (DB2G db2g) toDmDecimal(value []byte, column *column, conn *DmConnection) (*DmDecimal, error) {
+
+	switch column.colType {
+	case BIT, BOOLEAN, TINYINT:
+		if value == nil || len(value) == 0 {
+			return NewDecimalFromInt64(0)
+		} else {
+			return NewDecimalFromInt64(int64(value[0]))
+		}
+	case SMALLINT:
+		return NewDecimalFromInt64(int64(Dm_build_1.Dm_build_98(value, 0)))
+	case INT:
+		return NewDecimalFromInt64(int64(Dm_build_1.Dm_build_103(value, 0)))
+	case BIGINT:
+		return NewDecimalFromInt64(Dm_build_1.Dm_build_108(value, 0))
+	case REAL:
+		return NewDecimalFromFloat64(float64(Dm_build_1.Dm_build_113(value, 0)))
+	case DOUBLE:
+		return NewDecimalFromFloat64(Dm_build_1.Dm_build_117(value, 0))
+	case DECIMAL:
+		return decodeDecimal(value, int(column.prec), int(column.scale))
+	case CHAR, VARCHAR, VARCHAR2, CLOB:
+		return DB2G.charToDeciaml(value, column, conn)
+	}
+
+	return nil, ECGO_DATA_CONVERTION_ERROR
+}
+
+func (DB2G db2g) toTime(bytes []byte, column *column, conn *DmConnection) (time.Time, error) {
+	switch column.colType {
+	case DATE, TIME, TIME_TZ, DATETIME_TZ, DATETIME, DATETIME2_TZ, DATETIME2:
+		dt := decode(bytes, column.isBdta, *column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
+		return toTimeFromDT(dt, int(conn.dmConnector.localTimezone)), nil
+	case CHAR, VARCHAR2, VARCHAR, CLOB:
+		return toTimeFromString(DB2G.charToString(bytes, column, conn), int(conn.dmConnector.localTimezone)), nil
+	}
+	return time.Now(), ECGO_DATA_CONVERTION_ERROR.throw()
+}
+
+func (DB2G db2g) toObject(bytes []byte, column *column, conn *DmConnection) (interface{}, error) {
+
+	switch column.colType {
+	case BIT, BOOLEAN:
+		return bytes[0] != 0, nil
+
+	case TINYINT:
+
+		return Dm_build_1.Dm_build_94(bytes, 0), nil
+	case SMALLINT:
+		return Dm_build_1.Dm_build_98(bytes, 0), nil
+	case INT:
+		return Dm_build_1.Dm_build_103(bytes, 0), nil
+	case BIGINT:
+		return Dm_build_1.Dm_build_108(bytes, 0), nil
+	case DECIMAL:
+		return DB2G.decToDecimal(bytes, int(column.prec), int(column.scale), conn.CompatibleOracle())
+	case REAL:
+		return Dm_build_1.Dm_build_113(bytes, 0), nil
+	case DOUBLE:
+		return Dm_build_1.Dm_build_117(bytes, 0), nil
+	case DATE, TIME, DATETIME, TIME_TZ, DATETIME_TZ, DATETIME2, DATETIME2_TZ:
+		dt := decode(bytes, column.isBdta, *column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
+		return toTimeFromDT(dt, int(conn.dmConnector.localTimezone)), nil
+	case BINARY, VARBINARY:
+		return bytes, nil
+	case BLOB:
+		blob := newBlobFromDB(bytes, conn, column, conn.lobFetchAll())
+
+		if util.StringUtil.EqualsIgnoreCase(column.typeName, "LONGVARBINARY") {
+
+			l, err := blob.GetLength()
+			if err != nil {
+				return nil, err
+			}
+			return blob.getBytes(1, int32(l))
+		} else {
+			return blob, nil
+		}
+	case CHAR, VARCHAR, VARCHAR2:
+		val := DB2G.charToString(bytes, column, conn)
+		if column.mask == MASK_BFILE {
+
+		}
+
+		return val, nil
+	case CLOB:
+		clob := newClobFromDB(bytes, conn, column, conn.lobFetchAll())
+		if util.StringUtil.EqualsIgnoreCase(column.typeName, "LONGVARCHAR") {
+
+			l, err := clob.GetLength()
+			if err != nil {
+				return nil, err
+			}
+			return clob.getSubString(1, int32(l))
+		} else {
+			return clob, nil
+		}
+	case INTERVAL_YM:
+		return newDmIntervalYMByBytes(bytes), nil
+	case INTERVAL_DT:
+		return newDmIntervalDTByBytes(bytes), nil
+	case ARRAY:
+		return TypeDataSV.bytesToArray(bytes, nil, column.typeDescriptor)
+	case SARRAY:
+		return TypeDataSV.bytesToSArray(bytes, nil, column.typeDescriptor)
+	case CLASS:
+
+	case PLTYPE_RECORD:
+
+	default:
+		return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+	}
+
+	return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+}
+
+func (DB2G db2g) toComplexType(bytes []byte, column *column, conn *DmConnection) (interface{}, error) {
+	switch column.colType {
+	case BLOB:
+		if !isComplexType(int(column.colType), int(column.scale)) {
+			return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+		}
+		blob := newBlobFromDB(bytes, conn, column, true)
+		return TypeDataSV.objBlobToObj(blob, column.typeDescriptor)
+	case ARRAY:
+		return TypeDataSV.bytesToArray(bytes, nil, column.typeDescriptor)
+	case SARRAY:
+		return TypeDataSV.bytesToSArray(bytes, nil, column.typeDescriptor)
+	case CLASS:
+		return TypeDataSV.bytesToObj(bytes, nil, column.typeDescriptor)
+	case PLTYPE_RECORD:
+		return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+	default:
+		return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+	}
+}

+ 48 - 0
i18n/zj.go

@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package i18n
+
+import (
+	"encoding/json"
+	"golang.org/x/text/language"
+	"golang.org/x/text/message"
+)
+
+type msg struct {
+	Id          string `json:"id"`
+	Translation string `json:"translation,omitempty"`
+}
+
+type i18n struct {
+	Language string `json:"language"`
+	Messages []msg  `json:"messages"`
+}
+
+func InitConfig(jsonStr string) {
+
+	var i18n i18n
+	json.Unmarshal([]byte(jsonStr), &i18n)
+	msaArry := i18n.Messages
+	tag := language.MustParse(i18n.Language)
+	for _, e := range msaArry {
+		message.SetString(tag, e.Id, e.Translation)
+	}
+}
+
+func Get(key string, locale int) string {
+	var p *message.Printer
+
+	switch locale {
+	case 0:
+		p = message.NewPrinter(language.SimplifiedChinese)
+	case 1:
+		p = message.NewPrinter(language.AmericanEnglish)
+	case 2:
+		p = message.NewPrinter(language.TraditionalChinese)
+	}
+
+	return p.Sprintf(key)
+}

+ 240 - 0
i18n/zk.go

@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package i18n
+
+const Messages_en_US = `{
+  "language": "en-US",
+  "messages": [
+    {
+      "id": "error.dsn.invalidSchema",
+      "translation": "DSN must start with dm://"
+    },
+    {
+      "id": "error.unsupported.scan",
+      "translation": "Unsupported scan type"
+    },
+    {
+      "id": "error.invalidParameterNumber",
+      "translation": "Invalid parameter number"
+    },
+    {
+      "id": "error.initThirdPartCipherFailed",
+      "translation": "Init third part cipher failed"
+    },
+    {
+      "id": "error.connectionSwitchFailed",
+      "translation": "Connection switch failed"
+    },
+    {
+      "id": "error.connectionSwitched",
+      "translation": "Connection has been switched"
+    },
+    {
+      "id": "error.invalidServerMode",
+      "translation": "Invalid server mode"
+    },
+    {
+      "id": "error.osauthError",
+      "translation": "At the same time using the specifed user login and OS authentication login, please determine a way."
+    },
+    {
+      "id": "error.notQuerySQL",
+      "translation": "The SQL is not a query SQL"
+    },
+    {
+      "id": "error.notExecSQL",
+      "translation": "The SQL is not a execute SQL"
+    },
+    {
+      "id": "error.invalidTranIsolation",
+      "translation": "invalid Transaltion Isolation"
+    },
+    {
+      "id": "errorCommitInAutoCommitMode",
+      "translation": "Can't commit in Auto commit status"
+    },
+    {
+      "id": "errorCommitInAutoCommitMode",
+      "translation": "Can't rollback in Auto commit status"
+    },
+    {
+      "id": "errorStatementHandleClosed",
+      "translation": "Statement handle is closed"
+    },
+    {
+      "id": "errorResultSetColsed",
+      "translation": "Resultset is closed"
+    },
+    {
+      "id": "error.communicationError",
+      "translation": "Communication  error"
+    },
+    {
+      "id": "error.msgCheckError",
+      "translation": "Message check error"
+    },
+    {
+      "id": "error.unkownNetWork",
+      "translation": "Unkown net work"
+    },
+    {
+      "id": "error.serverVersion",
+      "translation": "Server version is too low"
+    },
+    {
+      "id": "error.usernameTooLong",
+      "translation": "Username is too long."
+    },
+    {
+      "id": "error.passwordTooLong",
+      "translation": "Password to login is too long."
+    },
+    {
+      "id": "error.dataTooLong",
+      "translation": "The data is too large to support."
+    },
+    {
+      "id": "error.invalidColumnType",
+      "translation": "Invalid column type"
+    },
+    {
+      "id": "error.dataConvertionError",
+      "translation": "Data convertion error"
+    },
+    {
+      "id": "error.invalidConn",
+      "translation": "Invalid connection"
+    },
+    {
+      "id": "error.invalidHex",
+      "translation": "Invalid Hex Number."
+    },
+	{
+      "id": "error.invalidBFile",
+      "translation": "Invalid BFile format string."
+    },
+    {
+      "id": "error.dataOverflow",
+      "translation": "Digital overflow"
+    },
+    {
+      "id": "error.invalidDateTimeFormat",
+      "translation": "Invalid datetime type format"
+    },
+    {
+      "id": "error.datetimeOverflow",
+      "translation": "Digital overflow"
+    },
+    {
+      "id": "error.invalidTimeInterval",
+      "translation": "Invalid time interval type value"
+    },
+    {
+      "id": "error.unsupportedInparamType",
+      "translation": "Unsupported input parameter type"
+    },
+    {
+      "id": "error.unsupportedOutparamType",
+      "translation": "Unsupported output parameter type"
+    },
+    {
+      "id": "error.unsupportedType",
+      "translation": "Not support this type"
+    },
+    {
+      "id": "error.invalidObjBlob",
+      "translation": "invalid Object Blob Data."
+    },
+    {
+      "id": "error.structMemNotMatch",
+      "translation": "Members are not matched in Record or Class"
+    },
+    {
+      "id": "error.invalidComplexTypeName",
+      "translation": "Invalid descriptor name."
+    },
+    {
+      "id": "error.invalidParamterValue",
+      "translation": "Invalid parameter value"
+    },
+    {
+      "id": "error.invalidArrayLen",
+      "translation": "the length of static array is bigger than the one when defined."
+    },
+    {
+      "id": "error.invalidSequenceNumber",
+      "translation": "Invalid sequence no"
+    },
+    {
+      "id": "error.resultsetInReadOnlyStatus",
+      "translation": "Resultset in readonly status"
+    },
+    {
+      "id": "error.SSLInitFailed",
+      "translation": "Failed to initialize SSL"
+    },
+    {
+      "id": "error.LobDataHasFreed",
+      "translation": "Lob Data has been freed"
+    },
+    {
+      "id": "error.fatalError",
+      "translation": "Fatal error"
+    },
+    {
+      "id": "error.invalidLenOrOffset",
+      "translation": "Invalid length or offset"
+    },
+    {
+      "id": "error.intervalValueOverflow",
+      "translation": "interval type value overflow"
+    },
+    {
+      "id": "error.invalidCipher",
+      "translation": "Invalid cipher type"
+    },
+    {
+      "id": "error.storeInNilPointer",
+      "translation": "Can't store value into a nil pointer"
+    },
+	{
+      "id": "error.batchError",
+	  "translation": "Error in executing with batch"
+	},
+	{
+      "id": "warning.bpWithErr",
+	  "translation": "Warning:Partial failure on execute with batch"
+	},
+	{
+      "id": "error.invalidSqlType",
+	  "translation": "Invalid sql type"
+	},
+	{
+      "id": "error.invalidDateTimeValue",
+	  "translation": "Invalid datetime value"
+	},
+	{
+      "id": "error.msgTooLong",
+	  "translation": "Message too long, limit 512M"
+	},
+	{
+      "id": "error.isNull",
+	  "translation": "Data is NULL"
+	},
+	{
+      "id": "error.ParamCountLimit",
+	  "translation": "Parameter count limit is 65536."
+	},
+	{
+      "id": "error.unbindedParameter",
+	  "translation": "Unbound parameter"
+	},
+	{
+      "id": "error.stringCut",
+	  "translation": "The string is cut"
+	}
+  ]
+}`

+ 240 - 0
i18n/zl.go

@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package i18n
+
+const Messages_zh_CN = `{
+  "language": "zh-Hans",
+  "messages": [
+    {
+      "id": "error.dsn.invalidSchema",
+      "translation": "DSN串必须以dm://开头"
+    },
+    {
+      "id": "error.unsupported.scan",
+      "translation": "Scan类型转换出错"
+    },
+    {
+      "id": "error.invalidParameterNumber",
+      "translation": "参数个数不匹配"
+    },
+    {
+      "id": "error.initThirdPartCipherFailed",
+      "translation": "第三方加密初始化失败"
+    },
+    {
+      "id": "error.connectionSwitchFailed",
+      "translation": "连接重置失败"
+    },
+    {
+      "id": "error.connectionSwitched",
+      "translation": "连接已重置"
+    },
+    {
+      "id": "error.invalidServerMode",
+      "translation": "服务器模式不匹配"
+    },
+    {
+      "id": "error.osauthError",
+      "translation": "同时使用了指定用户登录和OS认证登录, 请确定一种方式."
+    },
+    {
+      "id": "error.notQuerySQL",
+      "translation": "非查询SQL语句"
+    },
+    {
+      "id": "error.notExecSQL",
+      "translation": "非执行SQL语句"
+    },
+    {
+      "id": "error.invalidTranIsolation",
+      "translation": "非法的事务隔离级"
+    },
+    {
+      "id": "errorCommitInAutoCommitMode",
+      "translation": "自动提交模式下不能手动提交"
+    },
+    {
+      "id": "errorRollbackInAutoCommitMode",
+      "translation": "自动提交模式下不能手动回滚"
+    },
+    {
+      "id": "errorStatementHandleClosed",
+      "translation": "语句已经关闭"
+    },
+    {
+      "id": "errorResultSetColsed",
+      "translation": "结果集已经关闭"
+    },
+    {
+      "id": "error.communicationError",
+      "translation": "网络通信异常"
+    },
+    {
+      "id": "error.msgCheckError",
+      "translation": "消息校验异常"
+    },
+    {
+      "id": "error.unkownNetWork",
+      "translation": "未知的网络"
+    },
+    {
+      "id": "error.serverVersion",
+      "translation": "服务器版本太低"
+    },
+    {
+      "id": "error.usernameTooLong",
+      "translation": "用户名超长"
+    },
+    {
+      "id": "error.passwordTooLong",
+      "translation": "密码超长"
+    },
+    {
+      "id": "error.dataTooLong",
+      "translation": "数据大小已超过可支持范围"
+    },
+    {
+      "id": "error.invalidColumnType",
+      "translation": "无效的列类型"
+    },
+    {
+      "id": "error.dataConvertionError",
+      "translation": "类型转换异常"
+    },
+    {
+      "id": "error.invalidConn",
+      "translation": "连接失效"
+    },
+    {
+      "id": "error.invalidHex",
+      "translation": "无效的十六进制数字"
+    },
+	{
+      "id": "error.invalidBFile",
+      "translation": "无效的BFile格式串"
+    },
+    {
+      "id": "error.dataOverflow",
+      "translation": "数字溢出"
+    },
+    {
+      "id": "error.invalidDateTimeFormat",
+      "translation": "错误的日期时间类型格式"
+    },
+    {
+      "id": "error.datetimeOverflow",
+      "translation": "数字溢出"
+    },
+    {
+      "id": "error.invalidTimeInterval",
+      "translation": "错误的时间间隔类型数据"
+    },
+    {
+      "id": "error.unsupportedInparamType",
+      "translation": "输入参数类型不支持"
+    },
+    {
+      "id": "error.unsupportedOutparamType",
+      "translation": "输出参数类型不支持"
+    },
+    {
+      "id": "error.unsupportedType",
+      "translation": "不支持该数据类型"
+    },
+    {
+      "id": "error.invalidObjBlob",
+      "translation": "无效的对象BLOB数据"
+    },
+    {
+      "id": "error.structMemNotMatch",
+      "translation": "记录或类数据成员不匹配"
+    },
+    {
+      "id": "error.invalidComplexTypeName",
+      "translation": "无效的类型描述名称"
+    },
+    {
+      "id": "error.invalidParamterValue",
+      "translation": "无效的参数值"
+    },
+    {
+      "id": "error.invalidArrayLen",
+      "translation": "静态数组长度大于定义时长度"
+    },
+    {
+      "id": "error.invalidSequenceNumber",
+      "translation": "无效的列序号"
+    },
+    {
+      "id": "error.resultsetInReadOnlyStatus",
+      "translation": "结果集处于只读状态"
+    },
+    {
+      "id": "error.SSLInitFailed",
+      "translation": "初始化SSL环境失败"
+    },
+    {
+      "id": "error.LobDataHasFreed",
+      "translation": "LOB数据已经被释放"
+    },
+    {
+      "id": "error.fatalError",
+      "translation": "致命错误"
+    },
+    {
+      "id": "error.invalidLenOrOffset",
+      "translation": "长度或偏移错误"
+    },
+    {
+      "id": "error.intervalValueOverflow",
+      "translation": "时间间隔类型数据溢出"
+    },
+    {
+      "id": "error.invalidCipher",
+      "translation": "不支持的加密类型"
+    },
+    {
+      "id": "error.storeInNilPointer",
+      "translation": "无法将数据存入空指针"
+    },
+	{
+      "id": "error.batchError",
+	  "translation": "批量执行出错"
+	},
+	{
+      "id": "warning.bpWithErr",
+	  "translation": "警告:批量执行部分行产生错误"
+	},
+	{
+      "id": "error.invalidSqlType",
+	  "translation": "非法的SQL语句类型"
+	},
+	{
+      "id": "error.invalidDateTimeValue",
+	  "translation": "无效的日期时间类型值"
+	},
+	{
+      "id": "error.msgTooLong",
+	  "translation": "消息长度超出限制512M"
+	},
+	{
+      "id": "error.isNull",
+	  "translation": "数据为NULL"
+	},
+	{
+      "id": "error.ParamCountLimit",
+	  "translation": "参数个数超过最大值65536."
+	},
+	{
+      "id": "error.unbindedParameter",
+	  "translation": "有参数未绑定"
+	},
+	{
+      "id": "error.stringCut",
+	  "translation": "字符串截断"
+	}
+  ]
+}`

+ 28 - 0
i18n/zm.go

@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package i18n
+
+const Messages_zh_TW = `{
+  "language": "zh-Hant",
+  "messages": [
+    {
+      "id": "error.dsn.invalidSchema",
+      "translation": "DSN串必須以dm://開頭"
+    },
+    {
+      "id": "error.communicationError",
+      "translation": "網絡通信異常"
+    },
+    {
+      "id": "error.msgCheckError",
+      "translation": "消息校驗異常"
+    },
+    {
+      "id": "error.unkownNetWork",
+      "translation": "未知的網絡"
+    }
+  ]
+}`

+ 270 - 0
j.go

@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package dm
+
+import "database/sql/driver"
+
+type DmArray struct {
+	TypeData
+	m_arrDesc *ArrayDescriptor // 数组的描述信息
+
+	m_arrData []TypeData // 数组中各行数据值
+
+	m_objArray interface{} // 从服务端获取的
+
+	m_itemCount int // 本次获取的行数
+
+	m_itemSize int // 数组中一个数组项的大小,单位bytes
+
+	m_objCount int // 一个数组项中存在对象类型的个数(class、动态数组)
+
+	m_strCount int // 一个数组项中存在字符串类型的个数
+
+	m_objStrOffs []int // 对象在前,字符串在后
+
+	typeName string
+
+	elements []interface{}
+
+	// Valid为false代表DmArray数据在数据库中为NULL
+	Valid bool
+}
+
+func (da *DmArray) init() *DmArray {
+	da.initTypeData()
+	da.m_itemCount = 0
+	da.m_itemSize = 0
+	da.m_objCount = 0
+	da.m_strCount = 0
+	da.m_objStrOffs = nil
+	da.m_dumyData = nil
+	da.m_offset = 0
+
+	da.m_objArray = nil
+	da.Valid = true
+	return da
+}
+
+// 数据库自定义数组Array构造函数,typeName为库中定义的数组类型名称,elements为该数组类型的每个值
+//
+// 例如,自定义数组类型语句为:create or replace type myArray is array int[];
+//
+// 则绑入绑出的go对象为: val := dm.NewDmArray("myArray", []interface{} {123, 456})
+func NewDmArray(typeName string, elements []interface{}) *DmArray {
+	da := new(DmArray)
+	da.typeName = typeName
+	da.elements = elements
+	da.Valid = true
+	return da
+}
+
+func (da *DmArray) create(dc *DmConnection) (*DmArray, error) {
+	desc, err := newArrayDescriptor(da.typeName, dc)
+	if err != nil {
+		return nil, err
+	}
+	return da.createByArrayDescriptor(desc, dc)
+}
+
+func (da *DmArray) createByArrayDescriptor(arrDesc *ArrayDescriptor, conn *DmConnection) (*DmArray, error) {
+
+	if nil == arrDesc {
+		return nil, ECGO_INVALID_PARAMETER_VALUE.throw()
+	}
+
+	da.init()
+
+	da.m_arrDesc = arrDesc
+	if nil == da.elements {
+		da.m_arrData = make([]TypeData, 0)
+	} else {
+		// 若为静态数组,判断给定数组长度是否超过静态数组的上限
+		if arrDesc.getMDesc() == nil || (arrDesc.getMDesc().getDType() == SARRAY && len(da.elements) > arrDesc.getMDesc().getStaticArrayLength()) {
+			return nil, ECGO_INVALID_ARRAY_LEN.throw()
+		}
+
+		var err error
+		da.m_arrData, err = TypeDataSV.toArray(da.elements, da.m_arrDesc.getMDesc())
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	da.m_itemCount = len(da.m_arrData)
+	return da, nil
+}
+
+func newDmArrayByTypeData(atData []TypeData, desc *TypeDescriptor) *DmArray {
+	da := new(DmArray)
+	da.init()
+	da.m_arrDesc = newArrayDescriptorByTypeDescriptor(desc)
+	da.m_arrData = atData
+	return da
+}
+
+func (da *DmArray) checkIndex(index int64) error {
+	if index < 0 || index > int64(len(da.m_arrData)-1) {
+		return ECGO_INVALID_LENGTH_OR_OFFSET.throw()
+	}
+	return nil
+}
+
+func (da *DmArray) checkIndexAndCount(index int64, count int) error {
+	err := da.checkIndex(index)
+	if err != nil {
+		return err
+	}
+
+	if count <= 0 || index+int64(count) > int64(len(da.m_arrData)) {
+		return ECGO_INVALID_LENGTH_OR_OFFSET.throw()
+	}
+	return nil
+}
+
+// 获取Array对象在数据库中的类型名称
+func (da *DmArray) GetBaseTypeName() (string, error) {
+	if err := da.checkValid(); err != nil {
+		return "", err
+	}
+	return da.m_arrDesc.m_typeDesc.getFulName()
+}
+
+// 获取Array对象的go数组对象
+func (da *DmArray) GetArray() (interface{}, error) {
+	if da.m_arrData == nil || len(da.m_arrData) <= 0 {
+		return nil, nil
+	}
+
+	return TypeDataSV.toJavaArray(da, 0, len(da.m_arrData), da.m_arrDesc.getItemDesc().getDType())
+}
+
+// 获取Array对象的指定偏移和执行长度go数据对象 index从0开始
+func (da *DmArray) GetObjArray(index int64, count int) (interface{}, error) {
+	var err error
+	if err = da.checkValid(); err != nil {
+		return nil, err
+	}
+	if err = da.checkIndexAndCount(index, count); err != nil {
+		return nil, err
+	}
+
+	return TypeDataSV.toJavaArray(da, index, count, da.m_arrDesc.getItemDesc().getDType())
+}
+
+func (da *DmArray) GetIntArray(index int64, count int) ([]int, error) {
+	var err error
+	if err = da.checkValid(); err != nil {
+		return nil, err
+	}
+	if err = da.checkIndexAndCount(index, count); err != nil {
+		return nil, err
+	}
+
+	tmp, err := TypeDataSV.toNumericArray(da, index, count, ARRAY_TYPE_INTEGER)
+	if err != nil {
+		return nil, err
+	}
+	return tmp.([]int), nil
+}
+
+func (da *DmArray) GetInt16Array(index int64, count int) ([]int16, error) {
+	var err error
+	if err = da.checkValid(); err != nil {
+		return nil, err
+	}
+	if err = da.checkIndexAndCount(index, count); err != nil {
+		return nil, err
+	}
+
+	tmp, err := TypeDataSV.toNumericArray(da, index, count, ARRAY_TYPE_SHORT)
+	if err != nil {
+		return nil, err
+	}
+	return tmp.([]int16), nil
+}
+
+func (da *DmArray) GetInt64Array(index int64, count int) ([]int64, error) {
+	var err error
+	if err = da.checkValid(); err != nil {
+		return nil, err
+	}
+	if err = da.checkIndexAndCount(index, count); err != nil {
+		return nil, err
+	}
+
+	tmp, err := TypeDataSV.toNumericArray(da, index, count, ARRAY_TYPE_LONG)
+	if err != nil {
+		return nil, err
+	}
+
+	return tmp.([]int64), nil
+}
+
+func (da *DmArray) GetFloatArray(index int64, count int) ([]float32, error) {
+	var err error
+	if err = da.checkValid(); err != nil {
+		return nil, err
+	}
+	if err = da.checkIndexAndCount(index, count); err != nil {
+		return nil, err
+	}
+
+	tmp, err := TypeDataSV.toNumericArray(da, index, count, ARRAY_TYPE_FLOAT)
+	if err != nil {
+		return nil, err
+	}
+
+	return tmp.([]float32), nil
+}
+
+func (da *DmArray) GetDoubleArray(index int64, count int) ([]float64, error) {
+	var err error
+	if err = da.checkValid(); err != nil {
+		return nil, err
+	}
+	if err = da.checkIndexAndCount(index, count); err != nil {
+		return nil, err
+	}
+
+	tmp, err := TypeDataSV.toNumericArray(da, index, count, ARRAY_TYPE_DOUBLE)
+	if err != nil {
+		return nil, err
+	}
+
+	return tmp.([]float64), nil
+}
+
+func (dest *DmArray) Scan(src interface{}) error {
+	if dest == nil {
+		return ECGO_STORE_IN_NIL_POINTER.throw()
+	}
+	switch src := src.(type) {
+	case nil:
+		*dest = *new(DmArray)
+		// 将Valid标志置false表示数据库中该列为NULL
+		(*dest).Valid = false
+		return nil
+	case *DmArray:
+		*dest = *src
+		return nil
+	default:
+		return UNSUPPORTED_SCAN.throw()
+	}
+}
+
+func (array DmArray) Value() (driver.Value, error) {
+	if !array.Valid {
+		return nil, nil
+	}
+	return array, nil
+}
+
+func (array *DmArray) checkValid() error {
+	if !array.Valid {
+		return ECGO_IS_NULL.throw()
+	}
+	return nil
+}

+ 290 - 0
k.go

@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"database/sql/driver"
+	"io"
+)
+
+type DmBlob struct {
+	lob
+	data   []byte
+	offset int64
+}
+
+func newDmBlob() *DmBlob {
+	return &DmBlob{
+		lob: lob{
+			inRow:            true,
+			groupId:          -1,
+			fileId:           -1,
+			pageNo:           -1,
+			readOver:         false,
+			local:            true,
+			updateable:       true,
+			length:           -1,
+			compatibleOracle: false,
+			fetchAll:         false,
+			freed:            false,
+			modify:           false,
+			Valid:            true,
+		},
+		offset: 1,
+	}
+}
+
+func newBlobFromDB(value []byte, conn *DmConnection, column *column, fetchAll bool) *DmBlob {
+	var blob = newDmBlob()
+	blob.connection = conn
+	blob.lobFlag = LOB_FLAG_BYTE
+	blob.compatibleOracle = conn.CompatibleOracle()
+	blob.local = false
+	blob.updateable = !column.readonly
+	blob.tabId = column.lobTabId
+	blob.colId = column.lobColId
+
+	blob.inRow = Dm_build_1.Dm_build_94(value, NBLOB_HEAD_IN_ROW_FLAG) == LOB_IN_ROW
+	blob.blobId = Dm_build_1.Dm_build_108(value, NBLOB_HEAD_BLOBID)
+	if !blob.inRow {
+		blob.groupId = Dm_build_1.Dm_build_98(value, NBLOB_HEAD_OUTROW_GROUPID)
+		blob.fileId = Dm_build_1.Dm_build_98(value, NBLOB_HEAD_OUTROW_FILEID)
+		blob.pageNo = Dm_build_1.Dm_build_103(value, NBLOB_HEAD_OUTROW_PAGENO)
+	}
+	if conn.NewLobFlag {
+		blob.tabId = Dm_build_1.Dm_build_103(value, NBLOB_EX_HEAD_TABLE_ID)
+		blob.colId = Dm_build_1.Dm_build_98(value, NBLOB_EX_HEAD_COL_ID)
+		blob.rowId = Dm_build_1.Dm_build_108(value, NBLOB_EX_HEAD_ROW_ID)
+		blob.exGroupId = Dm_build_1.Dm_build_98(value, NBLOB_EX_HEAD_FPA_GRPID)
+		blob.exFileId = Dm_build_1.Dm_build_98(value, NBLOB_EX_HEAD_FPA_FILEID)
+		blob.exPageNo = Dm_build_1.Dm_build_103(value, NBLOB_EX_HEAD_FPA_PAGENO)
+	}
+	blob.resetCurrentInfo()
+
+	blob.length = blob.getLengthFromHead(value)
+	if blob.inRow {
+		blob.data = make([]byte, blob.length)
+		if conn.NewLobFlag {
+			Dm_build_1.Dm_build_57(blob.data, 0, value, NBLOB_EX_HEAD_SIZE, len(blob.data))
+		} else {
+			Dm_build_1.Dm_build_57(blob.data, 0, value, NBLOB_INROW_HEAD_SIZE, len(blob.data))
+		}
+	} else if fetchAll {
+		blob.loadAllData()
+	}
+	return blob
+}
+
+func newBlobOfLocal(value []byte, conn *DmConnection) *DmBlob {
+	var blob = newDmBlob()
+	blob.connection = conn
+	blob.lobFlag = LOB_FLAG_BYTE
+	blob.data = value
+	blob.length = int64(len(blob.data))
+	return blob
+}
+
+func NewBlob(value []byte) *DmBlob {
+	var blob = newDmBlob()
+
+	blob.lobFlag = LOB_FLAG_BYTE
+	blob.data = value
+	blob.length = int64(len(blob.data))
+	return blob
+}
+
+func (blob *DmBlob) Read(dest []byte) (n int, err error) {
+	if err = blob.checkValid(); err != nil {
+		return
+	}
+	result, err := blob.getBytes(blob.offset, int32(len(dest)))
+	if err != nil {
+		return 0, err
+	}
+	blob.offset += int64(len(result))
+	copy(dest, result)
+	if len(result) == 0 {
+		return 0, io.EOF
+	}
+	return len(result), nil
+}
+
+func (blob *DmBlob) ReadAt(pos int, dest []byte) (n int, err error) {
+	if err = blob.checkValid(); err != nil {
+		return
+	}
+	result, err := blob.getBytes(int64(pos), int32(len(dest)))
+	if err != nil {
+		return 0, err
+	}
+	if len(result) == 0 {
+		return 0, io.EOF
+	}
+	copy(dest[0:len(result)], result)
+	return len(result), nil
+}
+
+func (blob *DmBlob) Write(pos int, src []byte) (n int, err error) {
+	if err = blob.checkValid(); err != nil {
+		return
+	}
+	if err = blob.checkFreed(); err != nil {
+		return
+	}
+	if pos < 1 {
+		err = ECGO_INVALID_LENGTH_OR_OFFSET.throw()
+		return
+	}
+	if !blob.updateable {
+		err = ECGO_RESULTSET_IS_READ_ONLY.throw()
+		return
+	}
+	pos -= 1
+	if blob.local || blob.fetchAll {
+		if int64(pos) > blob.length {
+			err = ECGO_INVALID_LENGTH_OR_OFFSET.throw()
+			return
+		}
+		blob.setLocalData(pos, src)
+		n = len(src)
+	} else {
+		if err = blob.connection.checkClosed(); err != nil {
+			return -1, err
+		}
+		var writeLen, err = blob.connection.Access.dm_build_907(blob, pos, src)
+		if err != nil {
+			return -1, err
+		}
+
+		if blob.groupId == -1 {
+			blob.setLocalData(pos, src)
+		} else {
+			blob.inRow = false
+			blob.length = -1
+		}
+		n = writeLen
+
+	}
+	blob.modify = true
+	return
+}
+
+func (blob *DmBlob) Truncate(length int64) error {
+	var err error
+	if err = blob.checkValid(); err != nil {
+		return err
+	}
+	if err = blob.checkFreed(); err != nil {
+		return err
+	}
+	if length < 0 {
+		return ECGO_INVALID_LENGTH_OR_OFFSET.throw()
+	}
+	if !blob.updateable {
+		return ECGO_RESULTSET_IS_READ_ONLY.throw()
+	}
+	if blob.local || blob.fetchAll {
+		if length >= int64(len(blob.data)) {
+			return nil
+		}
+		tmp := make([]byte, length)
+		Dm_build_1.Dm_build_57(tmp, 0, blob.data, 0, len(tmp))
+		blob.data = tmp
+		blob.length = int64(len(tmp))
+	} else {
+		if err = blob.connection.checkClosed(); err != nil {
+			return err
+		}
+		blob.length, err = blob.connection.Access.dm_build_921(&blob.lob, int(length))
+		if err != nil {
+			return err
+		}
+		if blob.groupId == -1 {
+			tmp := make([]byte, blob.length)
+			Dm_build_1.Dm_build_57(tmp, 0, blob.data, 0, int(blob.length))
+			blob.data = tmp
+		}
+	}
+	blob.modify = true
+	return nil
+}
+
+func (dest *DmBlob) Scan(src interface{}) error {
+	if dest == nil {
+		return ECGO_STORE_IN_NIL_POINTER.throw()
+	}
+	switch src := src.(type) {
+	case nil:
+		*dest = *new(DmBlob)
+
+		(*dest).Valid = false
+		return nil
+	case []byte:
+		*dest = *NewBlob(src)
+		return nil
+	case *DmBlob:
+		*dest = *src
+		return nil
+	default:
+		return UNSUPPORTED_SCAN.throw()
+	}
+}
+
+func (blob DmBlob) Value() (driver.Value, error) {
+	if !blob.Valid {
+		return nil, nil
+	}
+	return blob, nil
+}
+
+func (blob *DmBlob) getBytes(pos int64, length int32) ([]byte, error) {
+	var err error
+	var leaveLength int64
+	if err = blob.checkFreed(); err != nil {
+		return nil, err
+	}
+	if pos < 1 || length < 0 {
+		return nil, ECGO_INVALID_LENGTH_OR_OFFSET.throw()
+	}
+	pos = pos - 1
+	if leaveLength, err = blob.GetLength(); err != nil {
+		return nil, err
+	}
+	leaveLength -= pos
+	if leaveLength < 0 {
+		return nil, ECGO_INVALID_LENGTH_OR_OFFSET.throw()
+	}
+	if int64(length) > leaveLength {
+		length = int32(leaveLength)
+	}
+	if blob.local || blob.inRow || blob.fetchAll {
+		return blob.data[pos : pos+int64(length)], nil
+	} else {
+
+		return blob.connection.Access.dm_build_870(blob, int32(pos), length)
+	}
+}
+
+func (blob *DmBlob) loadAllData() {
+	blob.checkFreed()
+	if blob.local || blob.inRow || blob.fetchAll {
+		return
+	}
+	len, _ := blob.GetLength()
+	blob.data, _ = blob.getBytes(1, int32(len))
+	blob.fetchAll = true
+}
+
+func (blob *DmBlob) setLocalData(pos int, p []byte) {
+	if pos+len(p) >= int(blob.length) {
+		var tmp = make([]byte, pos+len(p))
+		Dm_build_1.Dm_build_57(tmp, 0, blob.data, 0, pos)
+		Dm_build_1.Dm_build_57(tmp, pos, p, 0, len(p))
+		blob.data = tmp
+	} else {
+		Dm_build_1.Dm_build_57(blob.data, pos, p, 0, len(p))
+	}
+	blob.length = int64(len(blob.data))
+}

+ 272 - 0
l.go

@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"database/sql/driver"
+	"io"
+)
+
+type DmClob struct {
+	lob
+	data           []rune
+	serverEncoding string
+}
+
+func newDmClob() *DmClob {
+	return &DmClob{
+		lob: lob{
+			inRow:            true,
+			groupId:          -1,
+			fileId:           -1,
+			pageNo:           -1,
+			readOver:         false,
+			local:            true,
+			updateable:       true,
+			length:           -1,
+			compatibleOracle: false,
+			fetchAll:         false,
+			freed:            false,
+			modify:           false,
+			Valid:            true,
+		},
+	}
+}
+
+func newClobFromDB(value []byte, conn *DmConnection, column *column, fetchAll bool) *DmClob {
+	var clob = newDmClob()
+	clob.connection = conn
+	clob.lobFlag = LOB_FLAG_CHAR
+	clob.compatibleOracle = conn.CompatibleOracle()
+	clob.local = false
+	clob.updateable = !column.readonly
+	clob.tabId = column.lobTabId
+	clob.colId = column.lobColId
+
+	clob.inRow = Dm_build_1.Dm_build_94(value, NBLOB_HEAD_IN_ROW_FLAG) == LOB_IN_ROW
+	clob.blobId = Dm_build_1.Dm_build_108(value, NBLOB_HEAD_BLOBID)
+	if !clob.inRow {
+		clob.groupId = Dm_build_1.Dm_build_98(value, NBLOB_HEAD_OUTROW_GROUPID)
+		clob.fileId = Dm_build_1.Dm_build_98(value, NBLOB_HEAD_OUTROW_FILEID)
+		clob.pageNo = Dm_build_1.Dm_build_103(value, NBLOB_HEAD_OUTROW_PAGENO)
+	}
+	if conn.NewLobFlag {
+		clob.tabId = Dm_build_1.Dm_build_103(value, NBLOB_EX_HEAD_TABLE_ID)
+		clob.colId = Dm_build_1.Dm_build_98(value, NBLOB_EX_HEAD_COL_ID)
+		clob.rowId = Dm_build_1.Dm_build_108(value, NBLOB_EX_HEAD_ROW_ID)
+		clob.exGroupId = Dm_build_1.Dm_build_98(value, NBLOB_EX_HEAD_FPA_GRPID)
+		clob.exFileId = Dm_build_1.Dm_build_98(value, NBLOB_EX_HEAD_FPA_FILEID)
+		clob.exPageNo = Dm_build_1.Dm_build_103(value, NBLOB_EX_HEAD_FPA_PAGENO)
+	}
+	clob.resetCurrentInfo()
+
+	clob.serverEncoding = conn.getServerEncoding()
+	if clob.inRow {
+		if conn.NewLobFlag {
+			clob.data = []rune(Dm_build_1.Dm_build_158(value, NBLOB_EX_HEAD_SIZE, int(clob.getLengthFromHead(value)), clob.serverEncoding, conn))
+		} else {
+			clob.data = []rune(Dm_build_1.Dm_build_158(value, NBLOB_INROW_HEAD_SIZE, int(clob.getLengthFromHead(value)), clob.serverEncoding, conn))
+		}
+		clob.length = int64(len(clob.data))
+	} else if fetchAll {
+		clob.loadAllData()
+	}
+	return clob
+}
+
+func newClobOfLocal(value string, conn *DmConnection) *DmClob {
+	var clob = newDmClob()
+	clob.connection = conn
+	clob.lobFlag = LOB_FLAG_CHAR
+	clob.data = []rune(value)
+	clob.length = int64(len(clob.data))
+	return clob
+}
+
+func NewClob(value string) *DmClob {
+	var clob = newDmClob()
+
+	clob.lobFlag = LOB_FLAG_CHAR
+	clob.data = []rune(value)
+	clob.length = int64(len(clob.data))
+	return clob
+}
+
+func (clob *DmClob) ReadString(pos int, length int) (result string, err error) {
+	if err = clob.checkValid(); err != nil {
+		return
+	}
+	result, err = clob.getSubString(int64(pos), int32(length))
+	if err != nil {
+		return
+	}
+	if len(result) == 0 {
+		err = io.EOF
+		return
+	}
+	return
+}
+
+func (clob *DmClob) WriteString(pos int, s string) (n int, err error) {
+	if err = clob.checkValid(); err != nil {
+		return
+	}
+	if err = clob.checkFreed(); err != nil {
+		return
+	}
+	if pos < 1 {
+		err = ECGO_INVALID_LENGTH_OR_OFFSET.throw()
+		return
+	}
+	if !clob.updateable {
+		err = ECGO_RESULTSET_IS_READ_ONLY.throw()
+		return
+	}
+	pos -= 1
+	if clob.local || clob.fetchAll {
+		if int64(pos) > clob.length {
+			err = ECGO_INVALID_LENGTH_OR_OFFSET.throw()
+			return
+		}
+		clob.setLocalData(pos, s)
+		n = len(s)
+	} else {
+		if err = clob.connection.checkClosed(); err != nil {
+			return -1, err
+		}
+		var writeLen, err = clob.connection.Access.dm_build_891(clob, pos, s, clob.serverEncoding)
+		if err != nil {
+			return -1, err
+		}
+
+		if clob.groupId == -1 {
+			clob.setLocalData(pos, s)
+		} else {
+			clob.inRow = false
+			clob.length = -1
+		}
+		n = writeLen
+	}
+	clob.modify = true
+	return
+}
+
+func (clob *DmClob) Truncate(length int64) error {
+	var err error
+	if err = clob.checkValid(); err != nil {
+		return err
+	}
+	if err = clob.checkFreed(); err != nil {
+		return err
+	}
+	if length < 0 {
+		return ECGO_INVALID_LENGTH_OR_OFFSET.throw()
+	}
+	if !clob.updateable {
+		return ECGO_RESULTSET_IS_READ_ONLY.throw()
+	}
+	if clob.local || clob.fetchAll {
+		if length >= int64(len(clob.data)) {
+			return nil
+		}
+		clob.data = clob.data[0:length]
+		clob.length = int64(len(clob.data))
+	} else {
+		if err = clob.connection.checkClosed(); err != nil {
+			return err
+		}
+		clob.length, err = clob.connection.Access.dm_build_921(&clob.lob, int(length))
+		if err != nil {
+			return err
+		}
+		if clob.groupId == -1 {
+			clob.data = clob.data[0:clob.length]
+		}
+	}
+	clob.modify = true
+	return nil
+}
+
+func (dest *DmClob) Scan(src interface{}) error {
+	if dest == nil {
+		return ECGO_STORE_IN_NIL_POINTER.throw()
+	}
+	switch src := src.(type) {
+	case nil:
+		*dest = *new(DmClob)
+
+		(*dest).Valid = false
+		return nil
+	case string:
+		*dest = *NewClob(src)
+		return nil
+	case *DmClob:
+		*dest = *src
+		return nil
+	default:
+		return UNSUPPORTED_SCAN.throw()
+	}
+}
+
+func (clob DmClob) Value() (driver.Value, error) {
+	if !clob.Valid {
+		return nil, nil
+	}
+	return clob, nil
+}
+
+func (clob *DmClob) getSubString(pos int64, len int32) (string, error) {
+	var err error
+	var leaveLength int64
+	if err = clob.checkFreed(); err != nil {
+		return "", err
+	}
+	if pos < 1 || len < 0 {
+		return "", ECGO_INVALID_LENGTH_OR_OFFSET.throw()
+	}
+	pos = pos - 1
+	if leaveLength, err = clob.GetLength(); err != nil {
+		return "", err
+	}
+	if pos > leaveLength {
+		pos = leaveLength
+	}
+	leaveLength -= pos
+	if leaveLength < 0 {
+		return "", ECGO_INVALID_LENGTH_OR_OFFSET.throw()
+	}
+	if int64(len) > leaveLength {
+		len = int32(leaveLength)
+	}
+	if clob.local || clob.inRow || clob.fetchAll {
+		if pos > clob.length {
+			return "", ECGO_INVALID_LENGTH_OR_OFFSET.throw()
+		}
+		return string(clob.data[pos : pos+int64(len)]), nil
+	} else {
+
+		return clob.connection.Access.dm_build_880(clob, int32(pos), len)
+	}
+}
+
+func (clob *DmClob) loadAllData() {
+	clob.checkFreed()
+	if clob.local || clob.inRow || clob.fetchAll {
+		return
+	}
+	len, _ := clob.GetLength()
+	s, _ := clob.getSubString(1, int32(len))
+	clob.data = []rune(s)
+	clob.fetchAll = true
+}
+
+func (clob *DmClob) setLocalData(pos int, str string) {
+	if pos+len(str) >= int(clob.length) {
+		clob.data = []rune(string(clob.data[0:pos]) + str)
+	} else {
+		clob.data = []rune(string(clob.data[0:pos]) + str + string(clob.data[pos+len(str):len(clob.data)]))
+	}
+	clob.length = int64(len(clob.data))
+}

+ 891 - 0
m.go

@@ -0,0 +1,891 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"bytes"
+	"context"
+	"database/sql"
+	"database/sql/driver"
+	"fmt"
+	"sync/atomic"
+
+	"gitee.com/chunanyong/dm/parser"
+	"golang.org/x/text/encoding"
+)
+
+type DmConnection struct {
+	filterable
+
+	dmConnector        *DmConnector
+	Access             *dm_build_697
+	stmtMap            map[int32]*DmStatement
+	stmtPool           []stmtPoolInfo
+	lastExecInfo       *execRetInfo
+	lexer              *parser.Lexer
+	encode             encoding.Encoding
+	encodeBuffer       *bytes.Buffer
+	transformReaderDst []byte
+	transformReaderSrc []byte
+
+	serverEncoding     string
+	GlobalServerSeries int
+	ServerVersion      string
+	Malini2            bool
+	Execute2           bool
+	LobEmptyCompOrcl   bool
+	IsoLevel           int32
+	ReadOnly           bool
+	NewLobFlag         bool
+	sslEncrypt         int
+	MaxRowSize         int32
+	DDLAutoCommit      bool
+	BackslashEscape    bool
+	SvrStat            int32
+	SvrMode            int32
+	ConstParaOpt       bool
+	DbTimezone         int16
+	LifeTimeRemainder  int16
+	InstanceName       string
+	Schema             string
+	LastLoginIP        string
+	LastLoginTime      string
+	FailedAttempts     int32
+	LoginWarningID     int32
+	GraceTimeRemainder int32
+	Guid               string
+	DbName             string
+	StandbyHost        string
+	StandbyPort        int32
+	StandbyCount       int32
+	SessionID          int64
+	OracleDateLanguage byte
+	FormatDate         string
+	FormatTimestamp    string
+	FormatTimestampTZ  string
+	FormatTime         string
+	FormatTimeTZ       string
+	Local              bool
+	MsgVersion         int32
+	TrxStatus          int32
+	dscControl         bool
+	trxFinish          bool
+	sessionID          int64
+	autoCommit         bool
+	isBatch            bool
+
+	watching bool
+	watcher  chan<- context.Context
+	closech  chan struct{}
+	finished chan<- struct{}
+	canceled atomicError
+	closed   atomicBool
+}
+
+func (conn *DmConnection) setTrxFinish(status int32) {
+	switch status & Dm_build_1094 {
+	case Dm_build_1091, Dm_build_1092, Dm_build_1093:
+		conn.trxFinish = true
+	default:
+		conn.trxFinish = false
+	}
+}
+
+func (dmConn *DmConnection) init() {
+	if dmConn.dmConnector.stmtPoolMaxSize > 0 {
+		dmConn.stmtPool = make([]stmtPoolInfo, 0, dmConn.dmConnector.stmtPoolMaxSize)
+	}
+
+	dmConn.stmtMap = make(map[int32]*DmStatement)
+	dmConn.DbTimezone = 0
+	dmConn.GlobalServerSeries = 0
+	dmConn.MaxRowSize = 0
+	dmConn.LobEmptyCompOrcl = false
+	dmConn.ReadOnly = false
+	dmConn.DDLAutoCommit = false
+	dmConn.ConstParaOpt = false
+	dmConn.IsoLevel = -1
+	dmConn.sessionID = -1
+	dmConn.Malini2 = true
+	dmConn.NewLobFlag = true
+	dmConn.Execute2 = true
+	dmConn.serverEncoding = ENCODING_GB18030
+	dmConn.TrxStatus = Dm_build_1042
+	dmConn.OracleDateLanguage = byte(Locale)
+	dmConn.lastExecInfo = NewExceInfo()
+	dmConn.MsgVersion = Dm_build_975
+
+	dmConn.idGenerator = dmConnIDGenerator
+}
+
+func (dmConn *DmConnection) reset() {
+	dmConn.DbTimezone = 0
+	dmConn.GlobalServerSeries = 0
+	dmConn.MaxRowSize = 0
+	dmConn.LobEmptyCompOrcl = false
+	dmConn.ReadOnly = false
+	dmConn.DDLAutoCommit = false
+	dmConn.ConstParaOpt = false
+	dmConn.IsoLevel = -1
+	dmConn.sessionID = -1
+	dmConn.Malini2 = true
+	dmConn.NewLobFlag = true
+	dmConn.Execute2 = true
+	dmConn.serverEncoding = ENCODING_GB18030
+	dmConn.TrxStatus = Dm_build_1042
+}
+
+func (dc *DmConnection) checkClosed() error {
+	if dc.closed.IsSet() {
+		return driver.ErrBadConn
+	}
+
+	return nil
+}
+
+func (dc *DmConnection) executeInner(query string, execType int16) (interface{}, error) {
+
+	stmt, err := NewDmStmt(dc, query)
+
+	if err != nil {
+		return nil, err
+	}
+
+	if execType == Dm_build_1059 {
+		defer stmt.close()
+	}
+
+	stmt.innerUsed = true
+	if stmt.dmConn.dmConnector.escapeProcess {
+		stmt.nativeSql, err = stmt.dmConn.escape(stmt.nativeSql, stmt.dmConn.dmConnector.keyWords)
+		if err != nil {
+			stmt.close()
+			return nil, err
+		}
+	}
+
+	var optParamList []OptParameter
+
+	if stmt.dmConn.ConstParaOpt {
+		optParamList = make([]OptParameter, 0)
+		stmt.nativeSql, optParamList, err = stmt.dmConn.execOpt(stmt.nativeSql, optParamList, stmt.dmConn.getServerEncoding())
+		if err != nil {
+			stmt.close()
+			optParamList = nil
+		}
+	}
+
+	if execType == Dm_build_1058 && dc.dmConnector.enRsCache {
+		rpv, err := rp.get(stmt, query)
+		if err != nil {
+			return nil, err
+		}
+
+		if rpv != nil {
+			stmt.execInfo = rpv.execInfo
+			dc.lastExecInfo = rpv.execInfo
+			return newDmRows(rpv.getResultSet(stmt)), nil
+		}
+	}
+
+	var info *execRetInfo
+
+	if optParamList != nil && len(optParamList) > 0 {
+		info, err = dc.Access.Dm_build_776(stmt, optParamList)
+		if err != nil {
+			stmt.nativeSql = query
+			info, err = dc.Access.Dm_build_782(stmt, execType)
+		}
+	} else {
+		info, err = dc.Access.Dm_build_782(stmt, execType)
+	}
+
+	if err != nil {
+		stmt.close()
+		return nil, err
+	}
+	dc.lastExecInfo = info
+
+	if info.hasResultSet {
+		return newDmRows(newInnerRows(0, stmt, info)), nil
+	} else {
+		return newDmResult(stmt, info), nil
+	}
+}
+
+func g2dbIsoLevel(isoLevel int32) int32 {
+	switch isoLevel {
+	case 1:
+		return Dm_build_1046
+	case 2:
+		return Dm_build_1047
+	case 4:
+		return Dm_build_1048
+	case 6:
+		return Dm_build_1049
+	default:
+		return -1
+	}
+}
+
+func (dc *DmConnection) Begin() (driver.Tx, error) {
+	if len(dc.filterChain.filters) == 0 {
+		return dc.begin()
+	} else {
+		return dc.filterChain.reset().DmConnectionBegin(dc)
+	}
+}
+
+func (dc *DmConnection) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
+	if len(dc.filterChain.filters) == 0 {
+		return dc.beginTx(ctx, opts)
+	}
+	return dc.filterChain.reset().DmConnectionBeginTx(dc, ctx, opts)
+}
+
+func (dc *DmConnection) Commit() error {
+	if len(dc.filterChain.filters) == 0 {
+		return dc.commit()
+	} else {
+		return dc.filterChain.reset().DmConnectionCommit(dc)
+	}
+}
+
+func (dc *DmConnection) Rollback() error {
+	if len(dc.filterChain.filters) == 0 {
+		return dc.rollback()
+	} else {
+		return dc.filterChain.reset().DmConnectionRollback(dc)
+	}
+}
+
+func (dc *DmConnection) Close() error {
+	if len(dc.filterChain.filters) == 0 {
+		return dc.close()
+	} else {
+		return dc.filterChain.reset().DmConnectionClose(dc)
+	}
+}
+
+func (dc *DmConnection) Ping(ctx context.Context) error {
+	if len(dc.filterChain.filters) == 0 {
+		return dc.ping(ctx)
+	} else {
+		return dc.filterChain.reset().DmConnectionPing(dc, ctx)
+	}
+}
+
+func (dc *DmConnection) Exec(query string, args []driver.Value) (driver.Result, error) {
+	if len(dc.filterChain.filters) == 0 {
+		return dc.exec(query, args)
+	}
+	return dc.filterChain.reset().DmConnectionExec(dc, query, args)
+}
+
+func (dc *DmConnection) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
+	if len(dc.filterChain.filters) == 0 {
+		return dc.execContext(ctx, query, args)
+	}
+	return dc.filterChain.reset().DmConnectionExecContext(dc, ctx, query, args)
+}
+
+func (dc *DmConnection) Query(query string, args []driver.Value) (driver.Rows, error) {
+	if len(dc.filterChain.filters) == 0 {
+		return dc.query(query, args)
+	}
+	return dc.filterChain.reset().DmConnectionQuery(dc, query, args)
+}
+
+func (dc *DmConnection) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {
+	if len(dc.filterChain.filters) == 0 {
+		return dc.queryContext(ctx, query, args)
+	}
+	return dc.filterChain.reset().DmConnectionQueryContext(dc, ctx, query, args)
+}
+
+func (dc *DmConnection) Prepare(query string) (driver.Stmt, error) {
+	if len(dc.filterChain.filters) == 0 {
+		return dc.prepare(query)
+	}
+	return dc.filterChain.reset().DmConnectionPrepare(dc, query)
+}
+
+func (dc *DmConnection) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) {
+	if len(dc.filterChain.filters) == 0 {
+		return dc.prepareContext(ctx, query)
+	}
+	return dc.filterChain.reset().DmConnectionPrepareContext(dc, ctx, query)
+}
+
+func (dc *DmConnection) ResetSession(ctx context.Context) error {
+	if len(dc.filterChain.filters) == 0 {
+		return dc.resetSession(ctx)
+	}
+	return dc.filterChain.reset().DmConnectionResetSession(dc, ctx)
+}
+
+func (dc *DmConnection) CheckNamedValue(nv *driver.NamedValue) error {
+	if len(dc.filterChain.filters) == 0 {
+		return dc.checkNamedValue(nv)
+	}
+	return dc.filterChain.reset().DmConnectionCheckNamedValue(dc, nv)
+}
+
+func (dc *DmConnection) begin() (*DmConnection, error) {
+	return dc.beginTx(context.Background(), driver.TxOptions{driver.IsolationLevel(sql.LevelDefault), false})
+}
+
+func (dc *DmConnection) beginTx(ctx context.Context, opts driver.TxOptions) (*DmConnection, error) {
+	if err := dc.watchCancel(ctx); err != nil {
+		return nil, err
+	}
+	defer dc.finish()
+
+	err := dc.checkClosed()
+	if err != nil {
+		return nil, err
+	}
+
+	dc.autoCommit = false
+
+	if sql.IsolationLevel(opts.Isolation) == sql.LevelDefault {
+		opts.Isolation = driver.IsolationLevel(sql.LevelReadCommitted)
+	}
+
+	if dc.ReadOnly != opts.ReadOnly {
+		dc.ReadOnly = opts.ReadOnly
+		var readonly = 0
+		if opts.ReadOnly {
+			readonly = 1
+		}
+		dc.exec(fmt.Sprintf("SP_SET_SESSION_READONLY(%d)", readonly), nil)
+	}
+
+	if dc.IsoLevel != int32(opts.Isolation) {
+		switch sql.IsolationLevel(opts.Isolation) {
+		case sql.LevelDefault, sql.LevelReadUncommitted:
+			return dc, nil
+		case sql.LevelReadCommitted, sql.LevelSerializable:
+			dc.IsoLevel = int32(opts.Isolation)
+		case sql.LevelRepeatableRead:
+			if dc.CompatibleMysql() {
+				dc.IsoLevel = int32(sql.LevelReadCommitted)
+			} else {
+				return nil, ECGO_INVALID_TRAN_ISOLATION.throw()
+			}
+		default:
+			return nil, ECGO_INVALID_TRAN_ISOLATION.throw()
+		}
+
+		err = dc.Access.Dm_build_836(dc)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return dc, nil
+}
+
+func (dc *DmConnection) commit() error {
+	err := dc.checkClosed()
+	if err != nil {
+		return err
+	}
+
+	defer func() {
+		dc.autoCommit = dc.dmConnector.autoCommit
+		if dc.ReadOnly {
+			dc.exec("SP_SET_SESSION_READONLY(0)", nil)
+		}
+	}()
+
+	if !dc.autoCommit {
+		err = dc.Access.Commit()
+		if err != nil {
+			return err
+		}
+		dc.trxFinish = true
+		return nil
+	} else if !dc.dmConnector.alwayseAllowCommit {
+		return ECGO_COMMIT_IN_AUTOCOMMIT_MODE.throw()
+	}
+
+	return nil
+}
+
+func (dc *DmConnection) rollback() error {
+	err := dc.checkClosed()
+	if err != nil {
+		return err
+	}
+
+	defer func() {
+		dc.autoCommit = dc.dmConnector.autoCommit
+		if dc.ReadOnly {
+			dc.exec("SP_SET_SESSION_READONLY(0)", nil)
+		}
+	}()
+
+	if !dc.autoCommit {
+		err = dc.Access.Rollback()
+		if err != nil {
+			return err
+		}
+		dc.trxFinish = true
+		return nil
+	} else if !dc.dmConnector.alwayseAllowCommit {
+		return ECGO_ROLLBACK_IN_AUTOCOMMIT_MODE.throw()
+	}
+
+	return nil
+}
+
+func (dc *DmConnection) reconnect() error {
+	err := dc.Access.Close()
+	if err != nil {
+		return err
+	}
+
+	for _, stmt := range dc.stmtMap {
+		stmt.closed = true
+		for id, _ := range stmt.rsMap {
+			delete(stmt.rsMap, id)
+		}
+	}
+
+	if dc.stmtPool != nil {
+		dc.stmtPool = dc.stmtPool[:0]
+	}
+
+	dc.dmConnector.reConnection = dc
+
+	if dc.dmConnector.group != nil {
+		_, err = dc.dmConnector.group.connect(dc.dmConnector)
+		if err != nil {
+			return err
+		}
+	} else {
+		_, err = dc.dmConnector.connect(context.Background())
+	}
+
+	for _, stmt := range dc.stmtMap {
+		err = dc.Access.Dm_build_754(stmt)
+		if err != nil {
+			return err
+		}
+
+		if stmt.paramCount > 0 {
+			err = stmt.prepare()
+			if err != nil {
+				return err
+			}
+		}
+	}
+
+	return nil
+}
+
+func (dc *DmConnection) cleanup() {
+	dc.close()
+}
+
+func (dc *DmConnection) close() error {
+	if !dc.closed.TrySet(true) {
+		return nil
+	}
+
+	close(dc.closech)
+	if dc.Access == nil {
+		return nil
+	}
+
+	dc.rollback()
+
+	for _, stmt := range dc.stmtMap {
+		stmt.free()
+	}
+
+	if dc.stmtPool != nil {
+		for _, spi := range dc.stmtPool {
+			dc.Access.Dm_build_759(spi.id)
+		}
+		dc.stmtPool = nil
+	}
+
+	dc.Access.Close()
+
+	return nil
+}
+
+func (dc *DmConnection) ping(ctx context.Context) error {
+	if err := dc.watchCancel(ctx); err != nil {
+		return err
+	}
+	defer dc.finish()
+
+	rows, err := dc.query("select 1", nil)
+	if err != nil {
+		return err
+	}
+	return rows.close()
+}
+
+func (dc *DmConnection) exec(query string, args []driver.Value) (*DmResult, error) {
+	err := dc.checkClosed()
+	if err != nil {
+		return nil, err
+	}
+
+	if args != nil && len(args) > 0 {
+		stmt, err := dc.prepare(query)
+		defer stmt.close()
+		if err != nil {
+			return nil, err
+		}
+		dc.lastExecInfo = stmt.execInfo
+
+		return stmt.exec(args)
+	} else {
+		r1, err := dc.executeInner(query, Dm_build_1059)
+		if err != nil {
+			return nil, err
+		}
+
+		if r2, ok := r1.(*DmResult); ok {
+			return r2, nil
+		} else {
+			return nil, ECGO_NOT_EXEC_SQL.throw()
+		}
+	}
+}
+
+func (dc *DmConnection) execContext(ctx context.Context, query string, args []driver.NamedValue) (*DmResult, error) {
+	if err := dc.watchCancel(ctx); err != nil {
+		return nil, err
+	}
+	defer dc.finish()
+
+	err := dc.checkClosed()
+	if err != nil {
+		return nil, err
+	}
+
+	if args != nil && len(args) > 0 {
+		stmt, err := dc.prepare(query)
+		defer stmt.close()
+		if err != nil {
+			return nil, err
+		}
+		dc.lastExecInfo = stmt.execInfo
+		dargs, err := namedValueToValue(stmt, args)
+		if err != nil {
+			return nil, err
+		}
+		return stmt.exec(dargs)
+	} else {
+		r1, err := dc.executeInner(query, Dm_build_1059)
+		if err != nil {
+			return nil, err
+		}
+
+		if r2, ok := r1.(*DmResult); ok {
+			return r2, nil
+		} else {
+			return nil, ECGO_NOT_EXEC_SQL.throw()
+		}
+	}
+}
+
+func (dc *DmConnection) query(query string, args []driver.Value) (*DmRows, error) {
+
+	err := dc.checkClosed()
+	if err != nil {
+		return nil, err
+	}
+
+	if args != nil && len(args) > 0 {
+		stmt, err := dc.prepare(query)
+		if err != nil {
+			stmt.close()
+			return nil, err
+		}
+		dc.lastExecInfo = stmt.execInfo
+
+		stmt.innerUsed = true
+		return stmt.query(args)
+
+	} else {
+		r1, err := dc.executeInner(query, Dm_build_1058)
+		if err != nil {
+			return nil, err
+		}
+
+		if r2, ok := r1.(*DmRows); ok {
+			return r2, nil
+		} else {
+			return nil, ECGO_NOT_QUERY_SQL.throw()
+		}
+	}
+}
+
+func (dc *DmConnection) queryContext(ctx context.Context, query string, args []driver.NamedValue) (*DmRows, error) {
+	if err := dc.watchCancel(ctx); err != nil {
+		return nil, err
+	}
+	defer dc.finish()
+
+	err := dc.checkClosed()
+	if err != nil {
+		return nil, err
+	}
+
+	if args != nil && len(args) > 0 {
+		stmt, err := dc.prepare(query)
+		if err != nil {
+			stmt.close()
+			return nil, err
+		}
+		dc.lastExecInfo = stmt.execInfo
+
+		stmt.innerUsed = true
+		dargs, err := namedValueToValue(stmt, args)
+		if err != nil {
+			return nil, err
+		}
+		return stmt.query(dargs)
+
+	} else {
+		r1, err := dc.executeInner(query, Dm_build_1058)
+		if err != nil {
+			return nil, err
+		}
+
+		if r2, ok := r1.(*DmRows); ok {
+			return r2, nil
+		} else {
+			return nil, ECGO_NOT_QUERY_SQL.throw()
+		}
+	}
+
+}
+
+func (dc *DmConnection) prepare(query string) (*DmStatement, error) {
+	err := dc.checkClosed()
+	if err != nil {
+		return nil, err
+	}
+
+	stmt, err := NewDmStmt(dc, query)
+	if err != nil {
+		return nil, err
+	}
+
+	err = stmt.prepare()
+	return stmt, err
+}
+
+func (dc *DmConnection) prepareContext(ctx context.Context, query string) (*DmStatement, error) {
+	if err := dc.watchCancel(ctx); err != nil {
+		return nil, err
+	}
+	defer dc.finish()
+
+	err := dc.checkClosed()
+	if err != nil {
+		return nil, err
+	}
+
+	stmt, err := dc.prepare(query)
+	if err != nil {
+		return nil, err
+	}
+
+	return stmt, nil
+}
+
+func (dc *DmConnection) resetSession(ctx context.Context) error {
+	if err := dc.watchCancel(ctx); err != nil {
+		return err
+	}
+	defer dc.finish()
+
+	err := dc.checkClosed()
+	if err != nil {
+		return err
+	}
+
+	for _, stmt := range dc.stmtMap {
+		stmt.inUse = false
+	}
+
+	return nil
+}
+
+func (dc *DmConnection) checkNamedValue(nv *driver.NamedValue) error {
+	var err error
+	var cvt = converter{dc, false}
+	nv.Value, err = cvt.ConvertValue(nv.Value)
+	dc.isBatch = cvt.isBatch
+	return err
+}
+
+func (dc *DmConnection) driverQuery(query string) (*DmStatement, *DmRows, error) {
+	stmt, err := NewDmStmt(dc, query)
+	if err != nil {
+		return nil, nil, err
+	}
+	stmt.innerUsed = true
+	stmt.innerExec = true
+	info, err := dc.Access.Dm_build_782(stmt, Dm_build_1058)
+	if err != nil {
+		return nil, nil, err
+	}
+	dc.lastExecInfo = info
+	stmt.innerExec = false
+	return stmt, newDmRows(newInnerRows(0, stmt, info)), nil
+}
+
+func (dc *DmConnection) getIndexOnEPGroup() int32 {
+	if dc.dmConnector.group == nil || dc.dmConnector.group.epList == nil {
+		return -1
+	}
+	for i := 0; i < len(dc.dmConnector.group.epList); i++ {
+		ep := dc.dmConnector.group.epList[i]
+		if dc.dmConnector.host == ep.host && dc.dmConnector.port == ep.port {
+			return int32(i)
+		}
+	}
+	return -1
+}
+
+func (dc *DmConnection) getServerEncoding() string {
+	if dc.dmConnector.charCode != "" {
+		return dc.dmConnector.charCode
+	}
+	return dc.serverEncoding
+}
+
+func (dc *DmConnection) lobFetchAll() bool {
+	return dc.dmConnector.lobMode == 2
+}
+
+func (conn *DmConnection) CompatibleOracle() bool {
+	return conn.dmConnector.compatibleMode == COMPATIBLE_MODE_ORACLE
+}
+
+func (conn *DmConnection) CompatibleMysql() bool {
+	return conn.dmConnector.compatibleMode == COMPATIBLE_MODE_MYSQL
+}
+
+func (conn *DmConnection) cancel(err error) {
+	conn.canceled.Set(err)
+	conn.close()
+
+}
+
+func (conn *DmConnection) finish() {
+	if !conn.watching || conn.finished == nil {
+		return
+	}
+	select {
+	case conn.finished <- struct{}{}:
+		conn.watching = false
+	case <-conn.closech:
+	}
+}
+
+func (conn *DmConnection) startWatcher() {
+	watcher := make(chan context.Context, 1)
+	conn.watcher = watcher
+	finished := make(chan struct{})
+	conn.finished = finished
+	go func() {
+		for {
+			var ctx context.Context
+			select {
+			case ctx = <-watcher:
+			case <-conn.closech:
+				return
+			}
+
+			select {
+			case <-ctx.Done():
+				conn.cancel(ctx.Err())
+			case <-finished:
+			case <-conn.closech:
+				return
+			}
+		}
+	}()
+}
+
+func (conn *DmConnection) watchCancel(ctx context.Context) error {
+	if conn.watching {
+
+		conn.cleanup()
+		return nil
+	}
+
+	if err := ctx.Err(); err != nil {
+		return err
+	}
+
+	if ctx.Done() == nil {
+		return nil
+	}
+
+	if conn.watcher == nil {
+		return nil
+	}
+
+	conn.watching = true
+	conn.watcher <- ctx
+	return nil
+}
+
+type noCopy struct{}
+
+func (*noCopy) Lock() {}
+
+type atomicBool struct {
+	_noCopy noCopy
+	value   uint32
+}
+
+func (ab *atomicBool) IsSet() bool {
+	return atomic.LoadUint32(&ab.value) > 0
+}
+
+func (ab *atomicBool) Set(value bool) {
+	if value {
+		atomic.StoreUint32(&ab.value, 1)
+	} else {
+		atomic.StoreUint32(&ab.value, 0)
+	}
+}
+
+func (ab *atomicBool) TrySet(value bool) bool {
+	if value {
+		return atomic.SwapUint32(&ab.value, 1) == 0
+	}
+	return atomic.SwapUint32(&ab.value, 0) > 0
+}
+
+type atomicError struct {
+	_noCopy noCopy
+	value   atomic.Value
+}
+
+func (ae *atomicError) Set(value error) {
+	ae.value.Store(value)
+}
+
+func (ae *atomicError) Value() error {
+	if v := ae.value.Load(); v != nil {
+
+		return v.(error)
+	}
+	return nil
+}

+ 895 - 0
n.go

@@ -0,0 +1,895 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"bytes"
+	"context"
+	"database/sql/driver"
+	"net"
+	"net/url"
+	"os"
+	"path/filepath"
+	"regexp"
+	"runtime"
+	"strconv"
+	"strings"
+	"time"
+
+	"gitee.com/chunanyong/dm/util"
+)
+
+const (
+	TimeZoneKey              = "timeZone"
+	EnRsCacheKey             = "enRsCache"
+	RsCacheSizeKey           = "rsCacheSize"
+	RsRefreshFreqKey         = "rsRefreshFreq"
+	LoginPrimary             = "loginPrimary"
+	LoginModeKey             = "loginMode"
+	LoginStatusKey           = "loginStatus"
+	LoginDscCtrlKey          = "loginDscCtrl"
+	SwitchTimesKey           = "switchTimes"
+	SwitchIntervalKey        = "switchInterval"
+	EpSelectorKey            = "epSelector"
+	PrimaryKey               = "primaryKey"
+	KeywordsKey              = "keywords"
+	CompressKey              = "compress"
+	CompressIdKey            = "compressId"
+	LoginEncryptKey          = "loginEncrypt"
+	CommunicationEncryptKey  = "communicationEncrypt"
+	DirectKey                = "direct"
+	Dec2DoubleKey            = "dec2double"
+	RwSeparateKey            = "rwSeparate"
+	RwPercentKey             = "rwPercent"
+	RwAutoDistributeKey      = "rwAutoDistribute"
+	CompatibleModeKey        = "compatibleMode"
+	CompatibleOraKey         = "comOra"
+	CipherPathKey            = "cipherPath"
+	DoSwitchKey              = "doSwitch"
+	ClusterKey               = "cluster"
+	LanguageKey              = "language"
+	DbAliveCheckFreqKey      = "dbAliveCheckFreq"
+	RwStandbyRecoverTimeKey  = "rwStandbyRecoverTime"
+	LogLevelKey              = "logLevel"
+	LogDirKey                = "logDir"
+	LogBufferPoolSizeKey     = "logBufferPoolSize"
+	LogBufferSizeKey         = "logBufferSize"
+	LogFlusherQueueSizeKey   = "logFlusherQueueSize"
+	LogFlushFreqKey          = "logFlushFreq"
+	StatEnableKey            = "statEnable"
+	StatDirKey               = "statDir"
+	StatFlushFreqKey         = "statFlushFreq"
+	StatHighFreqSqlCountKey  = "statHighFreqSqlCount"
+	StatSlowSqlCountKey      = "statSlowSqlCount"
+	StatSqlMaxCountKey       = "statSqlMaxCount"
+	StatSqlRemoveModeKey     = "statSqlRemoveMode"
+	AddressRemapKey          = "addressRemap"
+	UserRemapKey             = "userRemap"
+	ConnectTimeoutKey        = "connectTimeout"
+	LoginCertificateKey      = "loginCertificate"
+	UrlKey                   = "url"
+	HostKey                  = "host"
+	PortKey                  = "port"
+	UserKey                  = "user"
+	PasswordKey              = "password"
+	RwStandbyKey             = "rwStandby"
+	IsCompressKey            = "isCompress"
+	RwHAKey                  = "rwHA"
+	RwIgnoreSqlKey           = "rwIgnoreSql"
+	AppNameKey               = "appName"
+	OsNameKey                = "osName"
+	MppLocalKey              = "mppLocal"
+	SocketTimeoutKey         = "socketTimeout"
+	SessionTimeoutKey        = "sessionTimeout"
+	ContinueBatchOnErrorKey  = "continueBatchOnError"
+	BatchAllowMaxErrorsKey   = "batchAllowMaxErrors"
+	EscapeProcessKey         = "escapeProcess"
+	AutoCommitKey            = "autoCommit"
+	MaxRowsKey               = "maxRows"
+	RowPrefetchKey           = "rowPrefetch"
+	BufPrefetchKey           = "bufPrefetch"
+	LobModeKey               = "LobMode"
+	StmtPoolSizeKey          = "StmtPoolSize"
+	IgnoreCaseKey            = "ignoreCase"
+	AlwayseAllowCommitKey    = "AlwayseAllowCommit"
+	BatchTypeKey             = "batchType"
+	BatchNotOnCallKey        = "batchNotOnCall"
+	IsBdtaRSKey              = "isBdtaRS"
+	ClobAsStringKey          = "clobAsString"
+	SslCertPathKey           = "sslCertPath"
+	SslKeyPathKey            = "sslKeyPath"
+	SslFilesPathKey          = "sslFilesPath"
+	KerberosLoginConfPathKey = "kerberosLoginConfPath"
+	UKeyNameKey              = "uKeyName"
+	UKeyPinKey               = "uKeyPin"
+	ColumnNameUpperCaseKey   = "columnNameUpperCase"
+	ColumnNameCaseKey        = "columnNameCase"
+	DatabaseProductNameKey   = "databaseProductName"
+	OsAuthTypeKey            = "osAuthType"
+	SchemaKey                = "schema"
+
+	DO_SWITCH_OFF             int32 = 0
+	DO_SWITCH_WHEN_CONN_ERROR int32 = 1
+	DO_SWITCH_WHEN_EP_RECOVER int32 = 2
+
+	CLUSTER_TYPE_NORMAL int32 = 0
+	CLUSTER_TYPE_RW     int32 = 1
+	CLUSTER_TYPE_DW     int32 = 2
+	CLUSTER_TYPE_DSC    int32 = 3
+	CLUSTER_TYPE_MPP    int32 = 4
+
+	EP_STATUS_OK    int32 = 1
+	EP_STATUS_ERROR int32 = 2
+
+	LOGIN_MODE_PRIMARY_FIRST int32 = 0
+
+	LOGIN_MODE_PRIMARY_ONLY int32 = 1
+
+	LOGIN_MODE_STANDBY_ONLY int32 = 2
+
+	LOGIN_MODE_STANDBY_FIRST int32 = 3
+
+	LOGIN_MODE_NORMAL_FIRST int32 = 4
+
+	SERVER_MODE_NORMAL int32 = 0
+
+	SERVER_MODE_PRIMARY int32 = 1
+
+	SERVER_MODE_STANDBY int32 = 2
+
+	SERVER_STATUS_MOUNT int32 = 3
+
+	SERVER_STATUS_OPEN int32 = 4
+
+	SERVER_STATUS_SUSPEND int32 = 5
+
+	COMPATIBLE_MODE_ORACLE int = 1
+
+	COMPATIBLE_MODE_MYSQL int = 2
+
+	LANGUAGE_CN int = 0
+
+	LANGUAGE_EN int = 1
+
+	COLUMN_NAME_NATURAL_CASE = 0
+
+	COLUMN_NAME_UPPER_CASE = 1
+
+	COLUMN_NAME_LOWER_CASE = 2
+
+	compressDef   = Dm_build_1053
+	compressIDDef = Dm_build_1054
+
+	charCodeDef = ""
+
+	enRsCacheDef = false
+
+	rsCacheSizeDef = 20
+
+	rsRefreshFreqDef = 10
+
+	loginModeDef = LOGIN_MODE_NORMAL_FIRST
+
+	loginStatusDef = 0
+
+	loginEncryptDef = true
+
+	loginCertificateDef = ""
+
+	dec2DoubleDef = false
+
+	rwHADef = false
+
+	rwStandbyDef = false
+
+	rwSeparateDef = false
+
+	rwPercentDef = 25
+
+	rwAutoDistributeDef = true
+
+	rwStandbyRecoverTimeDef = 1000
+
+	cipherPathDef = ""
+
+	urlDef = ""
+
+	userDef = "SYSDBA"
+
+	passwordDef = "SYSDBA"
+
+	hostDef = "localhost"
+
+	portDef = DEFAULT_PORT
+
+	appNameDef = ""
+
+	mppLocalDef = false
+
+	socketTimeoutDef = 0
+
+	connectTimeoutDef = 5000
+
+	sessionTimeoutDef = 0
+
+	osAuthTypeDef = Dm_build_1036
+
+	continueBatchOnErrorDef = false
+
+	escapeProcessDef = false
+
+	autoCommitDef = true
+
+	maxRowsDef = 0
+
+	rowPrefetchDef = Dm_build_1037
+
+	bufPrefetchDef = 0
+
+	lobModeDef = 1
+
+	stmtPoolMaxSizeDef = 15
+
+	ignoreCaseDef = true
+
+	alwayseAllowCommitDef = true
+
+	isBdtaRSDef = false
+
+	kerberosLoginConfPathDef = ""
+
+	uKeyNameDef = ""
+
+	uKeyPinDef = ""
+
+	databaseProductNameDef = ""
+
+	caseSensitiveDef = true
+
+	compatibleModeDef = 0
+)
+
+type DmConnector struct {
+	filterable
+
+	dmDriver *DmDriver
+
+	compress int
+
+	compressID int8
+
+	newClientType bool
+
+	charCode string
+
+	enRsCache bool
+
+	rsCacheSize int
+
+	rsRefreshFreq int
+
+	loginMode int32
+
+	loginStatus int
+
+	loginDscCtrl bool
+
+	switchTimes int32
+
+	switchInterval int
+
+	epSelector int32
+
+	keyWords []string
+
+	loginEncrypt bool
+
+	loginCertificate string
+
+	dec2Double bool
+
+	rwHA bool
+
+	rwStandby bool
+
+	rwSeparate bool
+
+	rwPercent int32
+
+	rwAutoDistribute bool
+
+	rwStandbyRecoverTime int
+
+	rwIgnoreSql bool
+
+	doSwitch int32
+
+	cluster int32
+
+	cipherPath string
+
+	url string
+
+	user string
+
+	password string
+
+	host string
+
+	group *epGroup
+
+	port int32
+
+	appName string
+
+	osName string
+
+	mppLocal bool
+
+	socketTimeout int
+
+	connectTimeout int
+
+	sessionTimeout int
+
+	osAuthType byte
+
+	continueBatchOnError bool
+
+	batchAllowMaxErrors int32
+
+	escapeProcess bool
+
+	autoCommit bool
+
+	maxRows int
+
+	rowPrefetch int
+
+	bufPrefetch int
+
+	lobMode int
+
+	stmtPoolMaxSize int
+
+	ignoreCase bool
+
+	alwayseAllowCommit bool
+
+	batchType int
+
+	batchNotOnCall bool
+
+	isBdtaRS bool
+
+	sslCertPath string
+
+	sslKeyPath string
+
+	sslFilesPath string
+
+	kerberosLoginConfPath string
+
+	uKeyName string
+
+	uKeyPin string
+
+	svcConfPath string
+
+	columnNameCase int
+
+	caseSensitive bool
+
+	compatibleMode int
+
+	localTimezone int16
+
+	schema string
+
+	reConnection *DmConnection
+
+	logLevel int
+
+	logDir string
+
+	logFlushFreq int
+
+	logFlushQueueSize int
+
+	logBufferSize int
+
+	statEnable bool
+
+	statDir string
+
+	statFlushFreq int
+
+	statSlowSqlCount int
+
+	statHighFreqSqlCount int
+
+	statSqlMaxCount int
+
+	statSqlRemoveMode int
+}
+
+func (c *DmConnector) init() *DmConnector {
+	c.compress = compressDef
+	c.compressID = compressIDDef
+	c.charCode = charCodeDef
+	c.enRsCache = enRsCacheDef
+	c.rsCacheSize = rsCacheSizeDef
+	c.rsRefreshFreq = rsRefreshFreqDef
+	c.loginMode = loginModeDef
+	c.loginStatus = loginStatusDef
+	c.loginDscCtrl = false
+	c.switchTimes = 1
+	c.switchInterval = 1000
+	c.epSelector = 0
+	c.keyWords = nil
+	c.loginEncrypt = loginEncryptDef
+	c.loginCertificate = loginCertificateDef
+	c.dec2Double = dec2DoubleDef
+	c.rwHA = rwHADef
+	c.rwStandby = rwStandbyDef
+	c.rwSeparate = rwSeparateDef
+	c.rwPercent = rwPercentDef
+	c.rwAutoDistribute = rwAutoDistributeDef
+	c.rwStandbyRecoverTime = rwStandbyRecoverTimeDef
+	c.rwIgnoreSql = false
+	c.doSwitch = DO_SWITCH_OFF
+	c.cluster = CLUSTER_TYPE_NORMAL
+	c.cipherPath = cipherPathDef
+	c.url = urlDef
+	c.user = userDef
+	c.password = passwordDef
+	c.host = hostDef
+	c.port = portDef
+	c.appName = appNameDef
+	c.osName = runtime.GOOS
+	c.mppLocal = mppLocalDef
+	c.socketTimeout = socketTimeoutDef
+	c.connectTimeout = connectTimeoutDef
+	c.sessionTimeout = sessionTimeoutDef
+	c.osAuthType = osAuthTypeDef
+	c.continueBatchOnError = continueBatchOnErrorDef
+	c.batchAllowMaxErrors = 0
+	c.escapeProcess = escapeProcessDef
+	c.autoCommit = autoCommitDef
+	c.maxRows = maxRowsDef
+	c.rowPrefetch = rowPrefetchDef
+	c.bufPrefetch = bufPrefetchDef
+	c.lobMode = lobModeDef
+	c.stmtPoolMaxSize = stmtPoolMaxSizeDef
+	c.ignoreCase = ignoreCaseDef
+	c.alwayseAllowCommit = alwayseAllowCommitDef
+	c.batchType = 1
+	c.batchNotOnCall = false
+	c.isBdtaRS = isBdtaRSDef
+	c.kerberosLoginConfPath = kerberosLoginConfPathDef
+	c.uKeyName = uKeyNameDef
+	c.uKeyPin = uKeyPinDef
+	c.columnNameCase = COLUMN_NAME_NATURAL_CASE
+	c.caseSensitive = caseSensitiveDef
+	c.compatibleMode = compatibleModeDef
+	_, tzs := time.Now().Zone()
+	c.localTimezone = int16(tzs / 60)
+	c.idGenerator = dmConntorIDGenerator
+
+	c.logDir = LogDirDef
+	c.logFlushFreq = LogFlushFreqDef
+	c.logFlushQueueSize = LogFlushQueueSizeDef
+	c.logBufferSize = LogBufferSizeDef
+	c.statEnable = StatEnableDef
+	c.statDir = StatDirDef
+	c.statFlushFreq = StatFlushFreqDef
+	c.statSlowSqlCount = StatSlowSqlCountDef
+	c.statHighFreqSqlCount = StatHighFreqSqlCountDef
+	c.statSqlMaxCount = StatSqlMaxCountDef
+	c.statSqlRemoveMode = StatSqlRemoveModeDef
+	return c
+}
+
+func (c *DmConnector) setAttributes(props *Properties) error {
+	if props == nil || props.Len() == 0 {
+		return nil
+	}
+
+	c.url = props.GetTrimString(UrlKey, c.url)
+	c.host = props.GetTrimString(HostKey, c.host)
+	c.port = int32(props.GetInt(PortKey, int(c.port), 0, 65535))
+	c.user = props.GetString(UserKey, c.user)
+	c.password = props.GetString(PasswordKey, c.password)
+	c.rwStandby = props.GetBool(RwStandbyKey, c.rwStandby)
+
+	if b := props.GetBool(IsCompressKey, false); b {
+		c.compress = Dm_build_1052
+	}
+
+	c.compress = props.GetInt(CompressKey, c.compress, 0, 2)
+	c.compressID = int8(props.GetInt(CompressIdKey, int(c.compressID), 0, 1))
+	c.enRsCache = props.GetBool(EnRsCacheKey, c.enRsCache)
+	c.localTimezone = int16(props.GetInt(TimeZoneKey, int(c.localTimezone), -720, 720))
+	c.rsCacheSize = props.GetInt(RsCacheSizeKey, c.rsCacheSize, 0, int(INT32_MAX))
+	c.rsRefreshFreq = props.GetInt(RsRefreshFreqKey, c.rsRefreshFreq, 0, int(INT32_MAX))
+	c.loginMode = int32(props.GetInt(LoginModeKey, int(c.loginMode), 0, 4))
+	c.loginStatus = props.GetInt(LoginStatusKey, c.loginStatus, 0, int(INT32_MAX))
+	c.loginDscCtrl = props.GetBool(LoginDscCtrlKey, c.loginDscCtrl)
+	c.switchTimes = int32(props.GetInt(SwitchTimesKey, int(c.switchTimes), 0, int(INT32_MAX)))
+	c.switchInterval = props.GetInt(SwitchIntervalKey, c.switchInterval, 0, int(INT32_MAX))
+	c.epSelector = int32(props.GetInt(EpSelectorKey, int(c.epSelector), 0, 1))
+	c.loginEncrypt = props.GetBool(LoginEncryptKey, c.loginEncrypt)
+	c.loginCertificate = props.GetTrimString(LoginCertificateKey, c.loginCertificate)
+	c.dec2Double = props.GetBool(Dec2DoubleKey, c.dec2Double)
+
+	c.rwSeparate = props.GetBool(RwSeparateKey, c.rwSeparate)
+	c.rwAutoDistribute = props.GetBool(RwAutoDistributeKey, c.rwAutoDistribute)
+	c.rwPercent = int32(props.GetInt(RwPercentKey, int(c.rwPercent), 0, 100))
+	c.rwHA = props.GetBool(RwHAKey, c.rwHA)
+	c.rwStandbyRecoverTime = props.GetInt(RwStandbyRecoverTimeKey, c.rwStandbyRecoverTime, 0, int(INT32_MAX))
+	c.rwIgnoreSql = props.GetBool(RwIgnoreSqlKey, c.rwIgnoreSql)
+	c.doSwitch = int32(props.GetInt(DoSwitchKey, int(c.doSwitch), 0, 2))
+	c.parseCluster(props)
+	c.cipherPath = props.GetTrimString(CipherPathKey, c.cipherPath)
+
+	if props.GetBool(CompatibleOraKey, false) {
+		c.compatibleMode = int(COMPATIBLE_MODE_ORACLE)
+	}
+	c.parseCompatibleMode(props)
+	c.keyWords = props.GetStringArray(KeywordsKey, c.keyWords)
+
+	c.appName = props.GetTrimString(AppNameKey, c.appName)
+	c.osName = props.GetTrimString(OsNameKey, c.osName)
+	c.mppLocal = props.GetBool(MppLocalKey, c.mppLocal)
+	c.socketTimeout = props.GetInt(SocketTimeoutKey, c.socketTimeout, 0, int(INT32_MAX))
+	c.connectTimeout = props.GetInt(ConnectTimeoutKey, c.connectTimeout, 0, int(INT32_MAX))
+	c.sessionTimeout = props.GetInt(SessionTimeoutKey, c.sessionTimeout, 0, int(INT32_MAX))
+
+	err := c.parseOsAuthType(props)
+	if err != nil {
+		return err
+	}
+	c.continueBatchOnError = props.GetBool(ContinueBatchOnErrorKey, c.continueBatchOnError)
+	c.batchAllowMaxErrors = int32(props.GetInt(BatchAllowMaxErrorsKey, int(c.batchAllowMaxErrors), 0, int(INT32_MAX)))
+	c.escapeProcess = props.GetBool(EscapeProcessKey, c.escapeProcess)
+	c.autoCommit = props.GetBool(AutoCommitKey, c.autoCommit)
+	c.maxRows = props.GetInt(MaxRowsKey, c.maxRows, 0, int(INT32_MAX))
+	c.rowPrefetch = props.GetInt(RowPrefetchKey, c.rowPrefetch, 0, int(INT32_MAX))
+	c.bufPrefetch = props.GetInt(BufPrefetchKey, c.bufPrefetch, int(Dm_build_1038), int(Dm_build_1039))
+	c.lobMode = props.GetInt(LobModeKey, c.lobMode, 1, 2)
+	c.stmtPoolMaxSize = props.GetInt(StmtPoolSizeKey, c.stmtPoolMaxSize, 0, int(INT32_MAX))
+	c.ignoreCase = props.GetBool(IgnoreCaseKey, c.ignoreCase)
+	c.alwayseAllowCommit = props.GetBool(AlwayseAllowCommitKey, c.alwayseAllowCommit)
+	c.batchType = props.GetInt(BatchTypeKey, c.batchType, 1, 2)
+	c.batchNotOnCall = props.GetBool(BatchNotOnCallKey, c.batchNotOnCall)
+	c.isBdtaRS = props.GetBool(IsBdtaRSKey, c.isBdtaRS)
+	c.sslFilesPath = props.GetTrimString(SslFilesPathKey, c.sslFilesPath)
+	c.sslCertPath = props.GetTrimString(SslCertPathKey, c.sslCertPath)
+	if c.sslCertPath == "" && c.sslFilesPath != "" {
+		c.sslCertPath = filepath.Join(c.sslFilesPath, "client-cert.pem")
+	}
+	c.sslKeyPath = props.GetTrimString(SslKeyPathKey, c.sslKeyPath)
+	if c.sslKeyPath == "" && c.sslFilesPath != "" {
+		c.sslKeyPath = filepath.Join(c.sslKeyPath, "client-key.pem")
+	}
+
+	c.kerberosLoginConfPath = props.GetTrimString(KerberosLoginConfPathKey, c.kerberosLoginConfPath)
+
+	c.uKeyName = props.GetTrimString(UKeyNameKey, c.uKeyName)
+	c.uKeyPin = props.GetTrimString(UKeyPinKey, c.uKeyPin)
+
+	c.svcConfPath = props.GetString("confPath", "")
+
+	if props.GetBool(ColumnNameUpperCaseKey, false) {
+		c.columnNameCase = COLUMN_NAME_UPPER_CASE
+	}
+
+	v := props.GetTrimString(ColumnNameCaseKey, "")
+	if util.StringUtil.EqualsIgnoreCase(v, "upper") {
+		c.columnNameCase = COLUMN_NAME_UPPER_CASE
+	} else if util.StringUtil.EqualsIgnoreCase(v, "lower") {
+		c.columnNameCase = COLUMN_NAME_LOWER_CASE
+	}
+
+	c.schema = props.GetTrimString(SchemaKey, c.schema)
+
+	c.logLevel = ParseLogLevel(props)
+	LogLevel = c.logLevel
+	c.logDir = util.StringUtil.FormatDir(props.GetTrimString(LogDirKey, LogDirDef))
+	LogDir = c.logDir
+	c.logBufferSize = props.GetInt(LogBufferSizeKey, LogBufferSizeDef, 1, int(INT32_MAX))
+	LogBufferSize = c.logBufferSize
+	c.logFlushFreq = props.GetInt(LogFlushFreqKey, LogFlushFreqDef, 1, int(INT32_MAX))
+	LogFlushFreq = c.logFlushFreq
+	c.logFlushQueueSize = props.GetInt(LogFlusherQueueSizeKey, LogFlushQueueSizeDef, 1, int(INT32_MAX))
+	LogFlushQueueSize = c.logFlushQueueSize
+
+	c.statEnable = props.GetBool(StatEnableKey, StatEnableDef)
+	StatEnable = c.statEnable
+	c.statDir = util.StringUtil.FormatDir(props.GetTrimString(StatDirKey, StatDirDef))
+	StatDir = c.statDir
+	c.statFlushFreq = props.GetInt(StatFlushFreqKey, StatFlushFreqDef, 1, int(INT32_MAX))
+	StatFlushFreq = c.statFlushFreq
+	c.statHighFreqSqlCount = props.GetInt(StatHighFreqSqlCountKey, StatHighFreqSqlCountDef, 0, 1000)
+	StatHighFreqSqlCount = c.statHighFreqSqlCount
+	c.statSlowSqlCount = props.GetInt(StatSlowSqlCountKey, StatSlowSqlCountDef, 0, 1000)
+	StatSlowSqlCount = c.statSlowSqlCount
+	c.statSqlMaxCount = props.GetInt(StatSqlMaxCountKey, StatSqlMaxCountDef, 0, 100000)
+	StatSqlMaxCount = c.statSqlMaxCount
+	c.parseStatSqlRemoveMode(props)
+	return nil
+}
+
+func (c *DmConnector) parseOsAuthType(props *Properties) error {
+	value := props.GetString(OsAuthTypeKey, "")
+	if value != "" && !util.StringUtil.IsDigit(value) {
+		if util.StringUtil.EqualsIgnoreCase(value, "ON") {
+			c.osAuthType = Dm_build_1036
+		} else if util.StringUtil.EqualsIgnoreCase(value, "SYSDBA") {
+			c.osAuthType = Dm_build_1032
+		} else if util.StringUtil.EqualsIgnoreCase(value, "SYSAUDITOR") {
+			c.osAuthType = Dm_build_1034
+		} else if util.StringUtil.EqualsIgnoreCase(value, "SYSSSO") {
+			c.osAuthType = Dm_build_1033
+		} else if util.StringUtil.EqualsIgnoreCase(value, "AUTO") {
+			c.osAuthType = Dm_build_1035
+		} else if util.StringUtil.EqualsIgnoreCase(value, "OFF") {
+			c.osAuthType = Dm_build_1031
+		}
+	} else {
+		c.osAuthType = byte(props.GetInt(OsAuthTypeKey, int(c.osAuthType), 0, 4))
+	}
+	if c.user == "" && c.osAuthType == Dm_build_1031 {
+		c.user = "SYSDBA"
+	} else if c.osAuthType != Dm_build_1031 && c.user != "" {
+		return ECGO_OSAUTH_ERROR.throw()
+	} else if c.osAuthType != Dm_build_1031 {
+		c.user = os.Getenv("user")
+		c.password = ""
+	}
+	return nil
+}
+
+func (c *DmConnector) parseCompatibleMode(props *Properties) {
+	value := props.GetString(CompatibleModeKey, "")
+	if value != "" && !util.StringUtil.IsDigit(value) {
+		if util.StringUtil.EqualsIgnoreCase(value, "oracle") {
+			c.compatibleMode = COMPATIBLE_MODE_ORACLE
+		} else if util.StringUtil.EqualsIgnoreCase(value, "mysql") {
+			c.compatibleMode = COMPATIBLE_MODE_MYSQL
+		}
+	} else {
+		c.compatibleMode = props.GetInt(CompatibleModeKey, c.compatibleMode, 0, 2)
+	}
+}
+
+func (c *DmConnector) parseStatSqlRemoveMode(props *Properties) {
+	value := props.GetString(StatSqlRemoveModeKey, "")
+	if value != "" && !util.StringUtil.IsDigit(value) {
+		if util.StringUtil.EqualsIgnoreCase("oldest", value) || util.StringUtil.EqualsIgnoreCase("eldest", value) {
+			c.statSqlRemoveMode = STAT_SQL_REMOVE_OLDEST
+		} else if util.StringUtil.EqualsIgnoreCase("latest", value) {
+			c.statSqlRemoveMode = STAT_SQL_REMOVE_LATEST
+		}
+	} else {
+		c.statSqlRemoveMode = props.GetInt(StatSqlRemoveModeKey, StatSqlRemoveModeDef, 1, 2)
+	}
+}
+
+func (c *DmConnector) parseCluster(props *Properties) {
+	value := props.GetTrimString(ClusterKey, "")
+	if util.StringUtil.EqualsIgnoreCase(value, "DSC") {
+		c.cluster = CLUSTER_TYPE_DSC
+	} else if util.StringUtil.EqualsIgnoreCase(value, "RW") {
+		c.cluster = CLUSTER_TYPE_RW
+	} else if util.StringUtil.EqualsIgnoreCase(value, "DW") {
+		c.cluster = CLUSTER_TYPE_DW
+	} else if util.StringUtil.EqualsIgnoreCase(value, "MPP") {
+		c.cluster = CLUSTER_TYPE_MPP
+	} else {
+		c.cluster = CLUSTER_TYPE_NORMAL
+	}
+}
+
+func (c *DmConnector) parseDSN(dsn string) (*Properties, string, error) {
+	var dsnProps = NewProperties()
+	url, err := url.Parse(dsn)
+	if err != nil {
+		return nil, "", err
+	}
+	if url.Scheme != "dm" {
+		return nil, "", DSN_INVALID_SCHEMA
+	}
+
+	if url.User != nil {
+		c.user = url.User.Username()
+		c.password, _ = url.User.Password()
+	}
+
+	q := url.Query()
+	for k := range q {
+		dsnProps.Set(k, q.Get(k))
+	}
+
+	return dsnProps, url.Host, nil
+}
+
+func (c *DmConnector) BuildDSN() string {
+	var buf bytes.Buffer
+
+	buf.WriteString("dm://")
+
+	if len(c.user) > 0 {
+		buf.WriteString(url.QueryEscape(c.user))
+		if len(c.password) > 0 {
+			buf.WriteByte(':')
+			buf.WriteString(url.QueryEscape(c.password))
+		}
+		buf.WriteByte('@')
+	}
+
+	if len(c.host) > 0 {
+		buf.WriteString(c.host)
+		if c.port > 0 {
+			buf.WriteByte(':')
+			buf.WriteString(strconv.Itoa(int(c.port)))
+		}
+	}
+
+	hasParam := false
+	if c.connectTimeout > 0 {
+		if hasParam {
+			buf.WriteString("&timeout=")
+		} else {
+			buf.WriteString("?timeout=")
+			hasParam = true
+		}
+		buf.WriteString(strconv.Itoa(c.connectTimeout))
+	}
+	return buf.String()
+}
+
+func (c *DmConnector) mergeConfigs(dsn string) error {
+	props, host, err := c.parseDSN(dsn)
+	if err != nil {
+		return err
+	}
+
+	driverInit(props.GetString("svcConfPath", ""))
+
+	addressRemapStr := props.GetTrimString(AddressRemapKey, "")
+	userRemapStr := props.GetTrimString(UserRemapKey, "")
+	if addressRemapStr == "" {
+		addressRemapStr = GlobalProperties.GetTrimString(AddressRemapKey, "")
+	}
+	if userRemapStr == "" {
+		userRemapStr = GlobalProperties.GetTrimString(UserRemapKey, "")
+	}
+
+	host = c.remap(host, addressRemapStr)
+
+	c.user = c.remap(c.user, userRemapStr)
+
+	if group, ok := ServerGroupMap[strings.ToLower(host)]; ok {
+		c.group = group
+	} else {
+		host, port, err := net.SplitHostPort(host)
+		if err != nil || net.ParseIP(host) == nil {
+			c.host = hostDef
+		} else {
+			c.host = host
+		}
+		tmpPort, err := strconv.Atoi(port)
+		if err != nil {
+			c.port = portDef
+		} else {
+			c.port = int32(tmpPort)
+		}
+
+		c.group = newEPGroup(c.host+":"+strconv.Itoa(int(c.port)), []*ep{newEP(c.host, c.port)})
+	}
+
+	props.SetDiffProperties(c.group.props)
+
+	props.SetDiffProperties(GlobalProperties)
+
+	if props.GetBool(RwSeparateKey, false) {
+		props.SetIfNotExist(LoginModeKey, strconv.Itoa(int(LOGIN_MODE_PRIMARY_ONLY)))
+		props.SetIfNotExist(LoginStatusKey, strconv.Itoa(int(SERVER_STATUS_OPEN)))
+
+		props.SetIfNotExist(DoSwitchKey, "true")
+	}
+
+	if err = c.setAttributes(props); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (c *DmConnector) remap(origin string, cfgStr string) string {
+	if cfgStr == "" || origin == "" {
+		return origin
+	}
+
+	maps := regexp.MustCompile("\\(.*?,.*?\\)").FindAllString(cfgStr, -1)
+	for _, kvStr := range maps {
+		kv := strings.Split(strings.TrimSpace(kvStr[1:len(kvStr)-1]), ",")
+		if util.StringUtil.Equals(strings.TrimSpace(kv[0]), origin) {
+			return strings.TrimSpace(kv[1])
+		}
+	}
+	return origin
+}
+
+func (c *DmConnector) Connect(ctx context.Context) (driver.Conn, error) {
+	return c.filterChain.reset().DmConnectorConnect(c, ctx)
+}
+
+func (c *DmConnector) Driver() driver.Driver {
+	return c.filterChain.reset().DmConnectorDriver(c)
+}
+
+func (c *DmConnector) connect(ctx context.Context) (*DmConnection, error) {
+	if c.group != nil && len(c.group.epList) > 0 {
+		return c.group.connect(c)
+	} else {
+		return c.connectSingle(ctx)
+	}
+}
+
+func (c *DmConnector) driver() *DmDriver {
+	return c.dmDriver
+}
+
+func (c *DmConnector) connectSingle(ctx context.Context) (*DmConnection, error) {
+	var err error
+	var dc *DmConnection
+	if c.reConnection == nil {
+		dc = &DmConnection{
+			closech: make(chan struct{}),
+		}
+		dc.dmConnector = c
+		dc.autoCommit = c.autoCommit
+		dc.createFilterChain(c, nil)
+
+		dc.objId = -1
+		dc.init()
+	} else {
+		dc = c.reConnection
+		dc.reset()
+	}
+
+	dc.Access, err = dm_build_709(dc)
+	if err != nil {
+		return nil, err
+	}
+
+	dc.startWatcher()
+	if err = dc.watchCancel(ctx); err != nil {
+		return nil, err
+	}
+	defer dc.finish()
+
+	if err = dc.Access.dm_build_750(); err != nil {
+
+		if !dc.closed.IsSet() {
+			close(dc.closech)
+			if dc.Access != nil {
+				dc.Access.Close()
+			}
+			dc.closed.Set(true)
+		}
+		return nil, err
+	}
+
+	if c.schema != "" {
+		_, err = dc.exec("set schema "+c.schema, nil)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return dc, nil
+}

+ 443 - 0
o.go

@@ -0,0 +1,443 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"database/sql/driver"
+	"math/big"
+	"reflect"
+	"strconv"
+	"strings"
+)
+
+const (
+	XDEC_MAX_PREC int = 38
+	XDEC_SIZE         = 21
+
+	FLAG_ZERO     int = 0x80
+	FLAG_POSITIVE int = 0xC1
+	FLAG_NEGTIVE  int = 0x3E
+	EXP_MAX       int = 0xFF - 1 - FLAG_POSITIVE
+	EXP_MIN       int = FLAG_NEGTIVE + 1 - 0x7F
+
+	NUM_POSITIVE int = 1
+	NUM_NEGTIVE  int = 101
+)
+
+type DmDecimal struct {
+	sign   int
+	weight int
+	prec   int
+	scale  int
+	digits string
+
+	Valid bool
+}
+
+func NewDecimalFromInt64(x int64) (*DmDecimal, error) {
+	return NewDecimalFromBigInt(big.NewInt(x))
+}
+
+func (d DmDecimal) ToInt64() int64 {
+	return d.ToBigInt().Int64()
+}
+
+func NewDecimalFromFloat64(x float64) (*DmDecimal, error) {
+	return NewDecimalFromBigFloat(big.NewFloat(x))
+}
+
+func (d DmDecimal) ToFloat64() float64 {
+	f, _ := d.ToBigFloat().Float64()
+	return f
+}
+
+func NewDecimalFromBigInt(bigInt *big.Int) (*DmDecimal, error) {
+	return newDecimal(bigInt, len(bigInt.String()), 0)
+}
+
+func (d DmDecimal) ToBigInt() *big.Int {
+	if d.isZero() {
+		return big.NewInt(0)
+	}
+	var digits = d.digits
+	if d.sign < 0 {
+		digits = "-" + digits
+	}
+	i1, ok := new(big.Int).SetString(digits, 10)
+	if !ok {
+		return nil
+	}
+	if d.weight > 0 {
+		i2, ok := new(big.Int).SetString("1"+strings.Repeat("0", d.weight), 10)
+		if !ok {
+			return nil
+		}
+		i1.Mul(i1, i2)
+	} else if d.weight < 0 {
+		i2, ok := new(big.Int).SetString("1"+strings.Repeat("0", -d.weight), 10)
+		if !ok {
+			return nil
+		}
+		i1.Quo(i1, i2)
+	}
+	return i1
+}
+
+func NewDecimalFromBigFloat(bigFloat *big.Float) (*DmDecimal, error) {
+	return newDecimal(bigFloat, int(bigFloat.Prec()), int(bigFloat.Prec()))
+}
+
+func (d DmDecimal) ToBigFloat() *big.Float {
+	if d.isZero() {
+		return big.NewFloat(0.0)
+	}
+	var digits = d.digits
+	if d.sign < 0 {
+		digits = "-" + digits
+	}
+	f1, ok := new(big.Float).SetString(digits)
+	if !ok {
+		return nil
+	}
+	if d.weight > 0 {
+		f2, ok := new(big.Float).SetString("1" + strings.Repeat("0", d.weight))
+		if !ok {
+			return nil
+		}
+		f1.Mul(f1, f2)
+	} else if d.weight < 0 {
+		f2, ok := new(big.Float).SetString("1" + strings.Repeat("0", -d.weight))
+		if !ok {
+			return nil
+		}
+		f1.Quo(f1, f2)
+	}
+	return f1
+}
+
+func NewDecimalFromString(s string) (*DmDecimal, error) {
+	num, ok := new(big.Float).SetString(strings.TrimSpace(s))
+	if !ok {
+		return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+	}
+	return NewDecimalFromBigFloat(num)
+}
+
+func (d DmDecimal) String() string {
+
+	if d.isZero() {
+		return "0"
+	}
+	digitsStr := d.digits
+	if d.weight > 0 {
+		digitsStr = digitsStr + strings.Repeat("0", d.weight)
+	} else if d.weight < 0 {
+		if len(digitsStr) < -d.weight {
+			digitsStr = strings.Repeat("0", -d.weight-len(digitsStr)+1) + digitsStr
+		}
+		indexOfDot := len(digitsStr) + d.weight
+		digitsStr = digitsStr[:indexOfDot] + "." + digitsStr[indexOfDot:]
+	}
+
+	if digitsStr[0] == '0' && digitsStr[1] != '.' {
+		digitsStr = digitsStr[1:]
+	}
+
+	if digitsStr[len(digitsStr)-1] == '0' && strings.IndexRune(digitsStr, '.') >= 0 {
+		digitsStr = digitsStr[0 : len(digitsStr)-1]
+	}
+
+	if d.sign < 0 {
+		digitsStr = "-" + digitsStr
+	}
+
+	return digitsStr
+}
+
+func (d DmDecimal) Sign() int {
+	return d.sign
+}
+
+func (dest *DmDecimal) Scan(src interface{}) error {
+	if dest == nil {
+		return ECGO_STORE_IN_NIL_POINTER.throw()
+	}
+	switch src := src.(type) {
+	case nil:
+		*dest = *new(DmDecimal)
+
+		(*dest).Valid = false
+		return nil
+	case int, int8, int16, int32, int64:
+		d, err := NewDecimalFromInt64(reflect.ValueOf(src).Int())
+		if err != nil {
+			return err
+		}
+		*dest = *d
+		return nil
+	case uint, uint8, uint16, uint32, uint64:
+		d, err := NewDecimalFromBigInt(new(big.Int).SetUint64(reflect.ValueOf(src).Uint()))
+		if err != nil {
+			return err
+		}
+		*dest = *d
+		return nil
+	case float32, float64:
+		d, err := NewDecimalFromFloat64(reflect.ValueOf(src).Float())
+		if err != nil {
+			return err
+		}
+		*dest = *d
+		return nil
+	case string:
+		d, err := NewDecimalFromString(src)
+		if err != nil {
+			return err
+		}
+		*dest = *d
+		return nil
+	case *DmDecimal:
+		*dest = *src
+		return nil
+	default:
+		return UNSUPPORTED_SCAN
+	}
+}
+
+func (d DmDecimal) Value() (driver.Value, error) {
+	if !d.Valid {
+		return nil, nil
+	}
+	return d, nil
+}
+
+func newDecimal(dec interface{}, prec int, scale int) (*DmDecimal, error) {
+	d := &DmDecimal{
+		prec:  prec,
+		scale: scale,
+		Valid: true,
+	}
+	if isFloat(DECIMAL, scale) {
+		d.prec = getFloatPrec(prec)
+		d.scale = -1
+	}
+	switch de := dec.(type) {
+	case *big.Int:
+		d.sign = de.Sign()
+
+		if d.isZero() {
+			return d, nil
+		}
+		str := de.String()
+
+		if d.sign < 0 {
+			str = str[1:]
+		}
+
+		if err := checkPrec(len(str), prec); err != nil {
+			return d, err
+		}
+		i := 0
+		istart := len(str) - 1
+
+		for i = istart; i > 0; i-- {
+			if str[i] != '0' {
+				break
+			}
+		}
+		str = str[:i+1]
+		d.weight += istart - i
+
+		if isOdd(d.weight) {
+			str += "0"
+			d.weight -= 1
+		}
+		if isOdd(len(str)) {
+			str = "0" + str
+		}
+		d.digits = str
+	case *big.Float:
+		d.sign = de.Sign()
+
+		if d.isZero() {
+			return d, nil
+		}
+		str := de.Text('f', -1)
+
+		if d.sign < 0 {
+			str = str[1:]
+		}
+
+		pointIndex := strings.IndexByte(str, '.')
+		i, istart, length := 0, 0, len(str)
+
+		if pointIndex != -1 {
+			if str[0] == '0' {
+
+				istart = 2
+				for i = istart; i < length; i++ {
+					if str[i] != '0' {
+						break
+					}
+				}
+				str = str[i:]
+				d.weight -= i - istart + len(str)
+			} else {
+				str = str[:pointIndex] + str[pointIndex+1:]
+				d.weight -= length - pointIndex - 1
+			}
+		}
+
+		length = len(str)
+		istart = length - 1
+		for i = istart; i > 0; i-- {
+			if str[i] != '0' {
+				break
+			}
+		}
+		str = str[:i+1] + str[length:]
+		d.weight += istart - i
+
+		if isOdd(d.weight) {
+			str += "0"
+			d.weight -= 1
+		}
+		if isOdd(len(str)) {
+			str = "0" + str
+		}
+		d.digits = str
+	case []byte:
+		return decodeDecimal(de, prec, scale)
+	}
+	return d, nil
+}
+
+func (d DmDecimal) encodeDecimal() ([]byte, error) {
+	if d.isZero() {
+		return []byte{byte(FLAG_ZERO)}, nil
+	}
+	exp := (d.weight+len(d.digits))/2 - 1
+	if exp > EXP_MAX || exp < EXP_MIN {
+		return nil, ECGO_DATA_TOO_LONG.throw()
+	}
+	validLen := len(d.digits)/2 + 1
+
+	if d.sign < 0 && validLen >= XDEC_SIZE {
+		validLen = XDEC_SIZE - 1
+	} else if validLen > XDEC_SIZE {
+		validLen = XDEC_SIZE
+	}
+	retLen := validLen
+	if d.sign < 0 {
+		retLen = validLen + 1
+	}
+	retBytes := make([]byte, retLen)
+	if d.sign > 0 {
+		retBytes[0] = byte(exp + FLAG_POSITIVE)
+	} else {
+		retBytes[0] = byte(FLAG_NEGTIVE - exp)
+	}
+
+	ibytes := 1
+	for ichar := 0; ibytes < validLen; {
+		digit1, err := strconv.Atoi(string(d.digits[ichar]))
+		if err != nil {
+			return nil, err
+		}
+		ichar++
+		digit2, err := strconv.Atoi(string(d.digits[ichar]))
+		ichar++
+		if err != nil {
+			return nil, err
+		}
+
+		digit := digit1*10 + digit2
+		if d.sign > 0 {
+			retBytes[ibytes] = byte(digit + NUM_POSITIVE)
+		} else {
+			retBytes[ibytes] = byte(NUM_NEGTIVE - digit)
+		}
+		ibytes++
+	}
+	if d.sign < 0 && ibytes < retLen {
+		retBytes[ibytes] = 0x66
+		ibytes++
+	}
+	if ibytes < retLen {
+		retBytes[ibytes] = 0x00
+	}
+	return retBytes, nil
+}
+
+func decodeDecimal(values []byte, prec int, scale int) (*DmDecimal, error) {
+	var decimal = &DmDecimal{
+		prec:   prec,
+		scale:  scale,
+		sign:   0,
+		weight: 0,
+		Valid:  true,
+	}
+	if values == nil || len(values) == 0 || len(values) > XDEC_SIZE {
+		return nil, ECGO_FATAL_ERROR.throw()
+	}
+	if values[0] == byte(FLAG_ZERO) || len(values) == 1 {
+		return decimal, nil
+	}
+	if values[0]&byte(FLAG_ZERO) != 0 {
+		decimal.sign = 1
+	} else {
+		decimal.sign = -1
+	}
+
+	var flag = int(Dm_build_1.Dm_build_121(values, 0))
+	var exp int
+	if decimal.sign > 0 {
+		exp = flag - FLAG_POSITIVE
+	} else {
+		exp = FLAG_NEGTIVE - flag
+	}
+	var digit = 0
+	var sf = ""
+	for ival := 1; ival < len(values); ival++ {
+		if decimal.sign > 0 {
+			digit = int(values[ival]) - NUM_POSITIVE
+		} else {
+			digit = NUM_NEGTIVE - int(values[ival])
+		}
+		if digit < 0 || digit > 99 {
+			break
+		}
+		if digit < 10 {
+			sf += "0"
+		}
+		sf += strconv.Itoa(digit)
+	}
+	decimal.digits = sf
+	decimal.weight = exp*2 - (len(decimal.digits) - 2)
+
+	return decimal, nil
+}
+
+func (d DmDecimal) isZero() bool {
+	return d.sign == 0
+}
+
+func checkPrec(len int, prec int) error {
+	if prec > 0 && len > prec || len > XDEC_MAX_PREC {
+		return ECGO_DATA_TOO_LONG.throw()
+	}
+	return nil
+}
+
+func isOdd(val int) bool {
+	return val%2 != 0
+}
+
+func (d *DmDecimal) checkValid() error {
+	if !d.Valid {
+		return ECGO_IS_NULL.throw()
+	}
+	return nil
+}

+ 86 - 0
p.go

@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"context"
+	"database/sql"
+	"database/sql/driver"
+	"sync"
+
+	"gitee.com/chunanyong/dm/i18n"
+)
+
+// 发版标记
+var version = "8.1.2.192"
+var build_date = "2023.01.05"
+var svn = "14827"
+
+var globalDmDriver = newDmDriver()
+
+func init() {
+	sql.Register("dm", globalDmDriver)
+}
+
+func driverInit(svcConfPath string) {
+	load(svcConfPath)
+	if GlobalProperties != nil && GlobalProperties.Len() > 0 {
+		setDriverAttributes(GlobalProperties)
+	}
+	globalDmDriver.createFilterChain(nil, GlobalProperties)
+
+	switch Locale {
+	case 0:
+		i18n.InitConfig(i18n.Messages_zh_CN)
+	case 1:
+		i18n.InitConfig(i18n.Messages_en_US)
+	case 2:
+		i18n.InitConfig(i18n.Messages_zh_TW)
+	}
+}
+
+type DmDriver struct {
+	filterable
+	readPropMutex sync.Mutex
+}
+
+func newDmDriver() *DmDriver {
+	d := new(DmDriver)
+	d.idGenerator = dmDriverIDGenerator
+	return d
+}
+
+/*************************************************************
+ ** PUBLIC METHODS AND FUNCTIONS
+ *************************************************************/
+func (d *DmDriver) Open(dsn string) (driver.Conn, error) {
+	return d.open(dsn)
+}
+
+func (d *DmDriver) OpenConnector(dsn string) (driver.Connector, error) {
+	return d.openConnector(dsn)
+}
+
+func (d *DmDriver) open(dsn string) (*DmConnection, error) {
+	c, err := d.openConnector(dsn)
+	if err != nil {
+		return nil, err
+	}
+	return c.connect(context.Background())
+}
+
+func (d *DmDriver) openConnector(dsn string) (*DmConnector, error) {
+	connector := new(DmConnector).init()
+	connector.url = dsn
+	connector.dmDriver = d
+	d.readPropMutex.Lock()
+	err := connector.mergeConfigs(dsn)
+	d.readPropMutex.Unlock()
+	if err != nil {
+		return nil, err
+	}
+	connector.createFilterChain(connector, nil)
+	return connector, nil
+}

+ 46 - 0
parser/zt.go

@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package parser
+
+import "strconv"
+
+const (
+	MAX_DEC_LEN = 38
+)
+
+const (
+	NORMAL int = iota
+	INT
+	DOUBLE
+	DECIMAL
+	STRING
+	HEX_INT
+	WHITESPACE_OR_COMMENT
+	NULL
+)
+
+type LVal struct {
+	Value    string
+	Tp       int
+	Position int
+}
+
+func newLValNoParams() *LVal {
+	return new(LVal).reset()
+}
+
+func newLVal(value string, tp int) *LVal {
+	return &LVal{Value: value, Tp: tp}
+}
+
+func (l *LVal) reset() *LVal {
+	l.Value = ""
+	l.Tp = NORMAL
+	return l
+}
+
+func (l *LVal) String() string {
+	return strconv.Itoa(l.Tp) + ":" + l.Value
+}

+ 1206 - 0
parser/zu.go

@@ -0,0 +1,1206 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package parser
+
+import (
+	"io"
+	"strconv"
+	"unicode/utf8"
+)
+
+const (
+	YYEOF         = -1    /** This character denotes the end of file */
+	ZZ_BUFFERSIZE = 16384 /** initial size of the lookahead buffer */
+	/** lexical states */
+	YYINITIAL = 0
+	xc        = 2
+	xq        = 4
+	xdq       = 6
+	xsb       = 8
+	xbin      = 10
+	xhex      = 12
+	xhint     = 14
+	xq2       = 16
+	xq2_2     = 18
+)
+
+/**
+* ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
+* ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l
+*                  at the beginning of a line
+* l is of the form l = 2*k, k a non negative integer
+ */
+var ZZ_LEXSTATE []int = []int{0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 4, 4, 7, 7, 8, 8}
+
+/**
+* Translates characters to character classes
+ */
+var ZZ_CMAP_PACKED []rune = []rune{0011, 0000, 0001, 0026, 0001, 0025, 0001, 0030, 0001, 0026, 0001, 0025, 0022, 0000, 0001, 0026, 0001, 0017, 0001, 0002,
+	0002, 0012, 0002, 0017, 0001, 0001, 0002, 0017, 0001, 0004, 0001, 0023, 0001, 0017, 0001, 0027, 0001, 0016, 0001, 0003,
+	0001, 0020, 0011, 0013, 0001, 0014, 0001, 0017, 0001, 0017, 0001, 0015, 0003, 0017, 0001, 0021, 0001, 0010, 0001, 0021,
+	0001, 0024, 0001, 0022, 0001, 0024, 0002, 0012, 0001, 0034, 0002, 0012, 0001, 0033, 0001, 0012, 0001, 0031, 0001, 0036,
+	0001, 0012, 0001, 0007, 0001, 0012, 0001, 0035, 0001, 0037, 0001, 0032, 0002, 0012, 0001, 0011, 0002, 0012, 0001, 0005,
+	0001, 0000, 0001, 0006, 0001, 0017, 0001, 0012, 0001, 0000, 0001, 0021, 0001, 0010, 0001, 0021, 0001, 0024, 0001, 0022,
+	0001, 0024, 0002, 0012, 0001, 0034, 0002, 0012, 0001, 0033, 0001, 0012, 0001, 0031, 0001, 0036, 0001, 0012, 0001, 0007,
+	0001, 0012, 0001, 0035, 0001, 0037, 0001, 0032, 0002, 0012, 0001, 0011, 0002, 0012, 0001, 0017, 0001, 0017, 0002, 0017,
+	0001, 0000, 0005, 0012, 0001, 0012, 0172, 0012, 0x1f28, 0000, 0001, 0030, 0001, 0030, 0xffff, 0000, 0xffff, 0000, 0xffff, 0000, 0xffff, 0000, 0xffff, 0000, 0xffff, 0000, 0xffff, 0000, 0xffff, 0000, 0xffff, 0000, 0xffff, 0000, 0xffff, 0000, 0xffff, 0000, 0xffff, 0000, 0xffff, 0000, 0xffff, 0000, 0xffff, 0000, 0xdfe6, 0000}
+
+/**
+* Translates characters to character classes
+ */
+var ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED)
+
+/**
+* Translates DFA states to action switch labels.
+ */
+var ZZ_ACTION = zzUnpackActionNoParams()
+
+var ZZ_ACTION_PACKED_0 []rune = []rune{0011, 0000, 0001, 0001, 0001, 0002, 0001, 0003, 0002, 0004, 0004, 0005, 0001, 0006, 0002, 0004,
+	0001, 0006, 0001, 0007, 0001, 0004, 0002, 0005, 0001, 0010, 0002, 0011, 0001, 0012, 0001, 0013,
+	0001, 0014, 0001, 0015, 0001, 0016, 0001, 0017, 0001, 0020, 0001, 0021, 0001, 0022, 0001, 0023,
+	0001, 0024, 0001, 0025, 0001, 0026, 0001, 0007, 0001, 0027, 0001, 0000, 0001, 0030, 0001, 0031,
+	0001, 0032, 0001, 0000, 0001, 0033, 0001, 0034, 0001, 0035, 0001, 0032, 0001, 0036, 0001, 0000,
+	0003, 0005, 0001, 0037, 0001, 0040, 0001, 0000, 0001, 0041, 0002, 0000, 0001, 0042, 0004, 0000,
+	0001, 0043, 0001, 0044, 0001, 0033, 0001, 0000, 0001, 0045, 0002, 0005, 0003, 0000, 0001, 0046,
+	0001, 0047, 0001, 0050, 0001, 0051, 0020, 0000, 0001, 0052, 0001, 0000, 0001, 0053, 0001, 0052,
+	0001, 0053}
+
+func zzUnpackActionNoParams() []int {
+	result := make([]int, 104)
+	offset := 0
+	offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result)
+	return result
+}
+
+func zzUnpackAction(packed []rune, offset int, result []int) int {
+	i := 0           /* index in packed string  */
+	j := offset      /* index in unpacked array */
+	l := len(packed) //130
+	for i < l {
+		count := packed[i]
+		i++
+		value := packed[i]
+		i++
+		result[j] = int(value)
+		j++
+		count--
+		for count > 0 {
+			result[j] = int(value)
+			j++
+			count--
+		}
+	}
+	return j
+}
+
+/**
+* Translates a state to a row index in the transition table
+ */
+var ZZ_ROWMAP = zzUnpackRowMapNoParams()
+
+var ZZ_ROWMAP_PACKED_0 []rune = []rune{0000, 0000, 0000, 0040, 0000, 0100, 0000, 0140, 0000, 0200, 0000, 0240, 0000, 0300, 0000, 0340,
+	0000, 0x0100, 0000, 0200, 0000, 0200, 0000, 0200, 0000, 0x0120, 0000, 0200, 0000, 0x0140, 0000, 0x0160,
+	0000, 0x0180, 0000, 0x01a0, 0000, 0x01c0, 0000, 0x01e0, 0000, 0x0200, 0000, 0x0220, 0000, 0200, 0000, 0x0240,
+	0000, 0x0260, 0000, 0x0280, 0000, 0x02a0, 0000, 0x02c0, 0000, 0x02e0, 0000, 0x0300, 0000, 0x0320, 0000, 0x0340,
+	0000, 0x0360, 0000, 0x0380, 0000, 0x03a0, 0000, 0x03c0, 0000, 0x03e0, 0000, 0x0400, 0000, 0200, 0000, 0200,
+	0000, 0200, 0000, 0200, 0000, 0x0420, 0000, 0200, 0000, 0x0440, 0000, 0200, 0000, 0200, 0000, 0x0460,
+	0000, 0x0480, 0000, 0200, 0000, 0200, 0000, 0200, 0000, 0x04a0, 0000, 0200, 0000, 0x04c0, 0000, 0x04e0,
+	0000, 0x0500, 0000, 0x0520, 0000, 0200, 0000, 0200, 0000, 0x02e0, 0000, 0200, 0000, 0x0540, 0000, 0x0560,
+	0000, 0200, 0000, 0x0580, 0000, 0x03a0, 0000, 0x05a0, 0000, 0x03e0, 0000, 0200, 0000, 0200, 0000, 0x05c0,
+	0000, 0x05c0, 0000, 0x04c0, 0000, 0x05e0, 0000, 0x0600, 0000, 0x0620, 0000, 0x0640, 0000, 0x0660, 0000, 0200,
+	0000, 0200, 0000, 0200, 0000, 0x01a0, 0000, 0x0680, 0000, 0x06a0, 0000, 0x06c0, 0000, 0x06e0, 0000, 0x0700,
+	0000, 0x0720, 0000, 0x0740, 0000, 0x0760, 0000, 0x0780, 0000, 0x07a0, 0000, 0x07c0, 0000, 0x07e0, 0000, 0x0800,
+	0000, 0x0820, 0000, 0x0840, 0000, 0x0860, 0000, 0200, 0000, 0x0880, 0000, 0200, 0000, 0x06e0, 0000, 0x0720}
+
+func zzUnpackRowMapNoParams() []int {
+	result := make([]int, 104)
+	offset := 0
+	offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result)
+	return result
+}
+
+func zzUnpackRowMap(packed []rune, offset int, result []int) int {
+	i := 0           /* index in packed string  */
+	j := offset      /* index in unpacked array */
+	l := len(packed) //208
+	for i < l {
+		high := packed[i] << 16
+		i++
+		result[j] = int(high | packed[i])
+		i++
+		j++
+	}
+	return j
+}
+
+/**
+* The transition table of the DFA
+ */
+var ZZ_TRANS []int = zzUnpackTransNoParams()
+
+var ZZ_TRANS_PACKED_0 []rune = []rune{0001, 0012, 0001, 0013, 0001, 0014, 0001, 0015, 0003, 0016, 0001, 0017, 0001, 0020, 0001, 0021,
+	0001, 0022, 0001, 0023, 0001, 0024, 0001, 0016, 0001, 0025, 0001, 0016, 0001, 0026, 0002, 0022,
+	0001, 0016, 0001, 0022, 0002, 0027, 0001, 0030, 0001, 0000, 0001, 0031, 0002, 0022, 0001, 0032,
+	0003, 0022, 0003, 0033, 0001, 0034, 0001, 0035, 0033, 0033, 0001, 0036, 0001, 0037, 0036, 0036,
+	0002, 0040, 0001, 0041, 0035, 0040, 0040, 0000, 0001, 0042, 0001, 0043, 0036, 0042, 0001, 0044,
+	0001, 0045, 0036, 0044, 0006, 0046, 0001, 0047, 0031, 0046, 0001, 0050, 0001, 0051, 0004, 0050,
+	0001, 0052, 0031, 0050, 0003, 0000, 0001, 0053, 0001, 0054, 0034, 0000, 0001, 0055, 0005, 0000,
+	0005, 0022, 0004, 0000, 0003, 0022, 0001, 0000, 0001, 0022, 0004, 0000, 0007, 0022, 0001, 0000,
+	0001, 0056, 0005, 0000, 0005, 0022, 0004, 0000, 0003, 0022, 0001, 0000, 0001, 0022, 0004, 0000,
+	0007, 0022, 0001, 0000, 0001, 0057, 0005, 0000, 0005, 0022, 0004, 0000, 0003, 0022, 0001, 0000,
+	0001, 0022, 0004, 0000, 0007, 0022, 0007, 0000, 0005, 0022, 0004, 0000, 0003, 0022, 0001, 0000,
+	0001, 0022, 0004, 0000, 0007, 0022, 0013, 0000, 0001, 0023, 0002, 0000, 0001, 0060, 0001, 0000,
+	0001, 0023, 0001, 0000, 0001, 0061, 0001, 0000, 0001, 0062, 0030, 0000, 0001, 0063, 0026, 0000,
+	0001, 0064, 0006, 0000, 0001, 0065, 0002, 0000, 0001, 0066, 0001, 0000, 0001, 0065, 0030, 0000,
+	0001, 0067, 0001, 0000, 0001, 0023, 0002, 0000, 0001, 0060, 0001, 0000, 0001, 0023, 0001, 0000,
+	0001, 0061, 0001, 0000, 0001, 0062, 0042, 0000, 0001, 0053, 0017, 0000, 0005, 0022, 0004, 0000,
+	0003, 0022, 0001, 0000, 0001, 0022, 0004, 0000, 0001, 0022, 0001, 0070, 0003, 0022, 0001, 0071,
+	0001, 0022, 0007, 0000, 0005, 0022, 0004, 0000, 0003, 0022, 0001, 0000, 0001, 0022, 0004, 0000,
+	0004, 0022, 0001, 0072, 0002, 0022, 0003, 0033, 0002, 0000, 0033, 0033, 0004, 0000, 0001, 0073,
+	0036, 0000, 0001, 0074, 0001, 0075, 0033, 0000, 0001, 0036, 0001, 0000, 0036, 0036, 0001, 0000,
+	0001, 0076, 0023, 0000, 0001, 0077, 0001, 0100, 0011, 0000, 0002, 0040, 0001, 0000, 0035, 0040,
+	0002, 0000, 0001, 0101, 0035, 0000, 0001, 0042, 0001, 0000, 0036, 0042, 0025, 0000, 0001, 0102,
+	0001, 0103, 0011, 0000, 0001, 0044, 0001, 0000, 0036, 0044, 0025, 0000, 0001, 0104, 0001, 0105,
+	0011, 0000, 0006, 0046, 0001, 0000, 0031, 0046, 0025, 0053, 0001, 0000, 0012, 0053, 0005, 0000,
+	0001, 0106, 0045, 0000, 0001, 0065, 0002, 0000, 0001, 0107, 0001, 0000, 0001, 0065, 0001, 0000,
+	0001, 0061, 0001, 0000, 0001, 0062, 0026, 0000, 0001, 0110, 0004, 0000, 0001, 0110, 0002, 0000,
+	0001, 0111, 0003, 0000, 0001, 0111, 0023, 0000, 0001, 0065, 0004, 0000, 0001, 0065, 0001, 0000,
+	0001, 0061, 0001, 0000, 0001, 0062, 0023, 0000, 0001, 0112, 0002, 0000, 0001, 0112, 0004, 0000,
+	0003, 0112, 0001, 0000, 0001, 0112, 0022, 0000, 0005, 0022, 0004, 0000, 0003, 0022, 0001, 0000,
+	0001, 0022, 0004, 0000, 0002, 0022, 0001, 0113, 0004, 0022, 0007, 0000, 0005, 0022, 0004, 0000,
+	0003, 0022, 0001, 0000, 0001, 0022, 0004, 0000, 0006, 0022, 0001, 0114, 0003, 0000, 0001, 0115,
+	0003, 0000, 0005, 0022, 0004, 0000, 0003, 0022, 0001, 0000, 0001, 0022, 0002, 0116, 0001, 0117,
+	0001, 0000, 0007, 0022, 0001, 0000, 0001, 0120, 0023, 0000, 0002, 0077, 0036, 0000, 0001, 0077,
+	0001, 0100, 0012, 0000, 0001, 0121, 0023, 0000, 0002, 0102, 0012, 0000, 0001, 0122, 0023, 0000,
+	0002, 0104, 0024, 0000, 0001, 0110, 0004, 0000, 0001, 0110, 0026, 0000, 0005, 0022, 0004, 0000,
+	0003, 0022, 0001, 0000, 0001, 0022, 0004, 0000, 0002, 0022, 0001, 0123, 0004, 0022, 0003, 0000,
+	0001, 0124, 0003, 0000, 0005, 0022, 0004, 0000, 0003, 0022, 0001, 0000, 0001, 0022, 0002, 0125,
+	0001, 0126, 0001, 0000, 0007, 0022, 0003, 0000, 0001, 0127, 0037, 0000, 0001, 0115, 0021, 0000,
+	0002, 0116, 0001, 0117, 0001, 0000, 0001, 0130, 0035, 0000, 0001, 0127, 0013, 0000, 0001, 0131,
+	0037, 0000, 0001, 0124, 0021, 0000, 0002, 0125, 0001, 0126, 0001, 0000, 0001, 0132, 0035, 0000,
+	0001, 0131, 0010, 0000, 0025, 0127, 0001, 0116, 0003, 0127, 0001, 0133, 0006, 0127, 0032, 0000,
+	0001, 0134, 0005, 0000, 0025, 0131, 0001, 0125, 0003, 0131, 0001, 0135, 0006, 0131, 0032, 0000,
+	0001, 0136, 0005, 0000, 0025, 0127, 0001, 0116, 0003, 0127, 0001, 0133, 0001, 0137, 0005, 0127,
+	0033, 0000, 0001, 0140, 0004, 0000, 0025, 0131, 0001, 0125, 0003, 0131, 0001, 0135, 0001, 0141,
+	0005, 0131, 0033, 0000, 0001, 0142, 0004, 0000, 0025, 0127, 0001, 0116, 0003, 0127, 0001, 0133,
+	0001, 0127, 0001, 0143, 0004, 0127, 0033, 0000, 0001, 0144, 0004, 0000, 0025, 0131, 0001, 0125,
+	0003, 0131, 0001, 0135, 0001, 0131, 0001, 0145, 0004, 0131, 0033, 0000, 0001, 0146, 0004, 0000,
+	0025, 0127, 0001, 0116, 0003, 0127, 0001, 0133, 0001, 0127, 0001, 0147, 0004, 0127, 0025, 0131,
+	0001, 0125, 0003, 0131, 0001, 0135, 0001, 0131, 0001, 0150, 0004, 0131}
+
+func zzUnpackTransNoParams() []int {
+	result := make([]int, 2208)
+	offset := 0
+	offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result)
+	return result
+}
+
+func zzUnpackTrans(packed []rune, offset int, result []int) int {
+	i := 0           /* index in packed string  */
+	j := offset      /* index in unpacked array */
+	l := len(packed) //780
+	for i < l {
+		count := packed[i]
+		i++
+		value := packed[i]
+		i++
+		value--
+		result[j] = int(value)
+		j++
+		count--
+		for count > 0 {
+			result[j] = int(value)
+			j++
+			count--
+		}
+	}
+	return j
+}
+
+/* error codes */
+const (
+	ZZ_UNKNOWN_ERROR = 0
+	ZZ_NO_MATCH      = 1
+	ZZ_PUSHBACK_2BIG = 2
+)
+
+/* error messages for the codes above */
+var ZZ_ERROR_MSG []string = []string{
+	"Unknown internal scanner error",
+	"Error: could not match input",
+	"Error: pushback Value was too large"}
+
+/**
+* ZZ_ATTRIBUTE[aState] contains the attributes of state <code>aState</code>
+ */
+var ZZ_ATTRIBUTE []int = zzUnpackAttributeNoParams()
+
+var ZZ_ATTRIBUTE_PACKED_0 []rune = []rune{0004, 0000, 0001, 0010, 0004, 0000, 0003, 0011, 0001, 0001, 0001, 0011, 0010, 0001, 0001, 0011,
+	0017, 0001, 0004, 0011, 0001, 0001, 0001, 0011, 0001, 0000, 0002, 0011, 0001, 0001, 0001, 0000,
+	0003, 0011, 0001, 0001, 0001, 0011, 0001, 0000, 0003, 0001, 0002, 0011, 0001, 0000, 0001, 0011,
+	0002, 0000, 0001, 0011, 0004, 0000, 0002, 0011, 0001, 0001, 0001, 0000, 0003, 0001, 0003, 0000,
+	0003, 0011, 0001, 0001, 0020, 0000, 0001, 0011, 0001, 0000, 0001, 0011, 0002, 0001}
+
+func zzUnpackAttributeNoParams() []int {
+	result := make([]int, 104)
+	offset := 0
+	offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result)
+	return result
+}
+
+func zzUnpackAttribute(packed []rune, offset int, result []int) int {
+	i := 0           /* index in packed string  */
+	j := offset      /* index in unpacked array */
+	l := len(packed) //78
+	for i < l {
+		count := packed[i]
+		i++
+		value := packed[i]
+		i++
+		result[j] = int(value)
+		j++
+		count--
+
+		for count > 0 {
+			result[j] = int(value)
+			j++
+			count--
+		}
+	}
+	return j
+}
+
+type Lexer struct {
+	/** the input device */
+	zzReader io.RuneReader
+
+	/** the current state of the DFA */
+	zzState int
+
+	/** the current lexical state */
+	zzLexicalState int
+
+	/** this buffer contains the current text to be matched and is
+	the source of the yytext() string */
+	zzBuffer []rune
+
+	//zzBytesBuffer []byte
+
+	/** the textposition at the last accepting state */
+	zzMarkedPos int
+
+	/** the current text Position in the buffer */
+	zzCurrentPos int
+
+	/** startRead marks the beginning of the yytext() string in the buffer */
+	zzStartRead int
+
+	/** endRead marks the last character in the buffer, that has been read
+	from input */
+	zzEndRead int
+
+	/** number of newlines encountered up to the start of the matched text */
+	yyline int
+
+	/** the number of characters up to the start of the matched text */
+	yychar int
+
+	/**
+	* the number of characters from the last newline up to the start of the
+	* matched text
+	 */
+	yycolumn int
+
+	/**
+	* zzAtBOL == true <=> the scanner is currently at the beginning of a line
+	 */
+	zzAtBOL bool
+
+	/** zzAtEOF == true <=> the scanner is at the EOF */
+	zzAtEOF bool
+
+	/** denotes if the user-EOF-code has already been executed */
+	zzEOFDone bool
+
+	/**
+	* The number of occupied positions in zzBuffer beyond zzEndRead.
+	* When a lead/high surrogate has been read from the input stream
+	* into the final zzBuffer Position, this will have a Value of 1;
+	* otherwise, it will have a Value of 0.
+	 */
+	zzFinalHighSurrogate int
+
+	/* user code: */
+	ltstr     string
+	debugFlag bool
+}
+
+func (lexer *Lexer) init() {
+	lexer.zzLexicalState = YYINITIAL
+	lexer.zzBuffer = make([]rune, ZZ_BUFFERSIZE)
+	lexer.zzAtBOL = true
+}
+
+func (lexer *Lexer) Reset(in io.RuneReader) *Lexer {
+	lexer.zzLexicalState = YYINITIAL
+	lexer.zzAtBOL = true
+	lexer.zzReader = in
+	lexer.zzState = 0
+	lexer.zzMarkedPos = 0
+	lexer.zzCurrentPos = 0
+	lexer.zzStartRead = 0
+	lexer.zzEndRead = 0
+	lexer.yyline = 0
+	lexer.yychar = 0
+	lexer.yycolumn = 0
+	lexer.zzAtEOF = false
+	lexer.zzEOFDone = false
+	lexer.zzFinalHighSurrogate = 0
+	lexer.ltstr = ""
+	return lexer
+}
+
+func (lexer *Lexer) debug(info string) {
+	if !lexer.debugFlag {
+		return
+	}
+
+}
+
+func (lexer *Lexer) yyerror(msg string) {
+	locInfo := "(line: " + strconv.Itoa(lexer.yyline) + ", column: " + strconv.Itoa(lexer.yycolumn) + ", char: " + strconv.Itoa(lexer.yychar) + ")"
+	if msg == "" {
+		panic("syntex error" + locInfo)
+	} else {
+		panic("syntex error" + locInfo + ": " + msg)
+	}
+}
+
+/**
+* Creates a new scanner
+*
+* @param   in  the java.io.Reader to read input from.
+ */
+func NewLexer(in io.RuneReader, debug bool) *Lexer {
+	l := new(Lexer)
+	l.init()
+	l.debugFlag = debug
+	l.zzReader = in
+	return l
+}
+
+/**
+* Unpacks the compressed character translation table.
+*
+* @param packed   the packed character translation table
+* @return         the unpacked character translation table
+ */
+func zzUnpackCMap(packed []rune) []rune {
+	m := make([]rune, 0x110000)
+	i := 0 /* index in packed string  */
+	j := 0 /* index in unpacked array */
+	for i < 208 {
+		count := packed[i]
+		i++
+		value := packed[i]
+		i++
+		m[j] = value
+		j++
+		count--
+		for count > 0 {
+			m[j] = value
+			j++
+			count--
+		}
+	}
+	return m
+}
+
+/**
+* Refills the input buffer.
+*
+* @return      <code>false</code>, iff there was new input.
+*
+* @exception   java.io.IOException  if any I/O-Error occurs
+ */
+func (lexer *Lexer) zzRefill() (bool, error) {
+
+	/* first: make room (if you can) */
+	if lexer.zzStartRead > 0 {
+		lexer.zzEndRead += lexer.zzFinalHighSurrogate
+		lexer.zzFinalHighSurrogate = 0
+		l := lexer.zzEndRead - lexer.zzStartRead
+		if l > 0 {
+			copy(lexer.zzBuffer[:l], lexer.zzBuffer[lexer.zzStartRead:lexer.zzEndRead])
+		}
+
+		/* translate stored positions */
+		lexer.zzEndRead -= lexer.zzStartRead
+		lexer.zzCurrentPos -= lexer.zzStartRead
+		lexer.zzMarkedPos -= lexer.zzStartRead
+		lexer.zzStartRead = 0
+	}
+
+	/* is the buffer big enough? */
+	if lexer.zzCurrentPos >= len(lexer.zzBuffer)-lexer.zzFinalHighSurrogate {
+		/* if not: blow it up */
+		newBuffer := make([]rune, len(lexer.zzBuffer)*2)
+
+		copy(newBuffer[:len(lexer.zzBuffer)], lexer.zzBuffer[:len(lexer.zzBuffer)])
+		lexer.zzBuffer = newBuffer
+		lexer.zzEndRead += lexer.zzFinalHighSurrogate
+		lexer.zzFinalHighSurrogate = 0
+	}
+
+	/* fill the buffer with new input */
+	requested := len(lexer.zzBuffer) - lexer.zzEndRead
+
+	var numRead = 0
+	for i := lexer.zzEndRead; i < lexer.zzEndRead+requested; i++ {
+		r, _, err := lexer.zzReader.ReadRune()
+		if err == io.EOF {
+			if numRead == 0 {
+				numRead = -1
+			}
+			break
+		} else if err != nil {
+			return false, err
+		} else {
+			numRead++
+			lexer.zzBuffer[i] = r
+		}
+	}
+
+	/* not supposed to occur according to specification of java.io.Reader */
+	if numRead == 0 {
+		panic("Reader returned 0 characters. See JFlex examples for workaround.")
+	}
+
+	if numRead > 0 {
+
+		lexer.zzEndRead += numRead
+		/* If numRead == requested, we might have requested to few chars to
+		   encode a full Unicode character. We assume that a Reader would
+		   otherwise never return half characters. */
+		if numRead == requested {
+			if utf8.ValidRune(lexer.zzBuffer[lexer.zzEndRead-1]) {
+				lexer.zzEndRead--
+				lexer.zzFinalHighSurrogate = 1
+			}
+		}
+		/* potentially more input available */
+		return false, nil
+	}
+
+	/* numRead < 0 ==> end of stream */
+	return true, nil
+}
+
+/**
+* Closes the input stream.
+ */
+func (lexer *Lexer) yyclose() error {
+	lexer.zzAtEOF = true                /* indicate end of file */
+	lexer.zzEndRead = lexer.zzStartRead /* invalidate buffer    */
+
+	if lexer.zzReader != nil {
+		if c, ok := lexer.zzReader.(io.Closer); ok {
+			return c.Close()
+		}
+	}
+	return nil
+}
+
+/**
+* Resets the scanner to read from a new input stream.
+* Does not close the old reader.
+*
+* All internal variables are reset, the old input stream
+* <b>cannot</b> be reused (internal buffer is discarded and lost).
+* Lexical state is set to <tt>ZZ_INITIAL</tt>.
+*
+* Internal scan buffer is resized down to its initial length, if it has grown.
+*
+* @param reader   the new input stream
+ */
+func (lexer *Lexer) yyreset(reader io.RuneReader) {
+	lexer.zzReader = reader
+	lexer.zzAtBOL = true
+	lexer.zzAtEOF = false
+	lexer.zzEOFDone = false
+	lexer.zzEndRead = 0
+	lexer.zzStartRead = 0
+	lexer.zzCurrentPos = 0
+	lexer.zzMarkedPos = 0
+	lexer.zzFinalHighSurrogate = 0
+	lexer.yyline = 0
+	lexer.yychar = 0
+	lexer.yycolumn = 0
+	lexer.zzLexicalState = YYINITIAL
+	if len(lexer.zzBuffer) > ZZ_BUFFERSIZE {
+		lexer.zzBuffer = make([]rune, ZZ_BUFFERSIZE)
+	}
+}
+
+/**
+* Returns the current lexical state.
+ */
+func (lexer *Lexer) yystate() int {
+	return lexer.zzLexicalState
+}
+
+/**
+* Enters a new lexical state
+*
+* @param newState the new lexical state
+ */
+func (lexer *Lexer) yybegin(newState int) {
+	lexer.zzLexicalState = newState
+}
+
+/**
+* Returns the text matched by the current regular expression.
+ */
+func (lexer *Lexer) yytext() string {
+	return string(lexer.zzBuffer[lexer.zzStartRead:lexer.zzMarkedPos])
+}
+
+/**
+* Returns the character at Position <tt>pos</tt> from the
+* matched text.
+*
+* It is equivalent to yytext().charAt(pos), but faster
+*
+* @param pos the Position of the character to fetch.
+*            A Value from 0 to yylength()-1.
+*
+* @return the character at Position pos
+ */
+func (lexer *Lexer) yycharat(pos int) rune {
+	return lexer.zzBuffer[lexer.zzStartRead+pos]
+}
+
+/**
+* Returns the length of the matched text region.
+ */
+func (lexer *Lexer) yylength() int {
+	return lexer.zzMarkedPos - lexer.zzStartRead
+}
+
+/**
+* Reports an error that occured while scanning.
+*
+* In a wellformed scanner (no or only correct usage of
+* yypushback(int) and a match-all fallback rule) this method
+* will only be called with things that "Can't Possibly Happen".
+* If this method is called, something is seriously wrong
+* (e.g. a JFlex bug producing a faulty scanner etc.).
+*
+* Usual syntax/scanner level error handling should be done
+* in error fallback rules.
+*
+* @param   errorCode  the code of the errormessage to display
+ */
+func (lexer *Lexer) zzScanError(errorCode int) {
+	var message string
+
+	message = ZZ_ERROR_MSG[errorCode]
+	if message == "" {
+		message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]
+	}
+
+	panic(message)
+}
+
+/**
+* Pushes the specified amount of characters back into the input stream.
+*
+* They will be read again by then next call of the scanning method
+*
+* @param number  the number of characters to be read again.
+*                This number must not be greater than yylength()!
+ */
+func (lexer *Lexer) yypushback(number int) {
+	if number > lexer.yylength() {
+		lexer.zzScanError(ZZ_PUSHBACK_2BIG)
+	}
+
+	lexer.zzMarkedPos -= number
+}
+
+/**
+* Resumes scanning until the next regular expression is matched,
+* the end of input is encountered or an I/O-Error occurs.
+*
+* @return      the next token
+* @exception   java.io.IOException  if any I/O-Error occurs
+ */
+func (lexer *Lexer) Yylex() (*LVal, error) {
+	var zzInput rune
+	var zzAction, zzCurrentPosL, zzMarkedPosL int
+	// cached fields:
+	zzEndReadL := lexer.zzEndRead
+	zzBufferL := lexer.zzBuffer
+	zzCMapL := ZZ_CMAP
+
+	zzTransL := ZZ_TRANS
+	zzRowMapL := ZZ_ROWMAP
+	zzAttrL := ZZ_ATTRIBUTE
+
+	for {
+		zzMarkedPosL = lexer.zzMarkedPos
+
+		lexer.yychar += zzMarkedPosL - lexer.zzStartRead
+
+		zzR := false
+		var zzCh rune
+		var zzCharCount int
+		zzCurrentPosL = lexer.zzStartRead
+		for zzCurrentPosL < zzMarkedPosL {
+			zzCh = zzBufferL[zzCurrentPosL]
+			zzCharCount = utf8.RuneLen(zzCh)
+			switch zzCh {
+			case '\u000B', '\u000C', '\u0085', '\u2028', '\u2029':
+				lexer.yyline++
+				lexer.yycolumn = 0
+				zzR = false
+			case '\r':
+				lexer.yyline++
+				lexer.yycolumn = 0
+				zzR = true
+			case '\n':
+				if zzR {
+					zzR = false
+				} else {
+					lexer.yyline++
+					lexer.yycolumn = 0
+				}
+			default:
+				zzR = false
+				lexer.yycolumn += zzCharCount
+			}
+			zzCurrentPosL += zzCharCount
+		}
+
+		if zzR {
+			// peek one character ahead if it is \n (if we have counted one line too much)
+			var zzPeek bool
+			if zzMarkedPosL < zzEndReadL {
+				zzPeek = zzBufferL[zzMarkedPosL] == '\n'
+			} else if lexer.zzAtEOF {
+				zzPeek = false
+			} else {
+				eof, err := lexer.zzRefill()
+				if err != nil {
+					return nil, err
+				}
+				zzEndReadL = lexer.zzEndRead
+				zzMarkedPosL = lexer.zzMarkedPos
+				zzBufferL = lexer.zzBuffer
+				if eof {
+					zzPeek = false
+				} else {
+					zzPeek = zzBufferL[zzMarkedPosL] == '\n'
+				}
+
+			}
+			if zzPeek {
+				lexer.yyline--
+			}
+		}
+		zzAction = -1
+
+		zzCurrentPosL = zzMarkedPosL
+		lexer.zzCurrentPos = zzMarkedPosL
+		lexer.zzStartRead = zzMarkedPosL
+		lexer.zzState = ZZ_LEXSTATE[lexer.zzLexicalState]
+
+		// set up zzAction for empty match case:
+		zzAttributes := zzAttrL[lexer.zzState]
+		if (zzAttributes & 1) == 1 {
+			zzAction = lexer.zzState
+		}
+
+		{
+			for true {
+
+				if zzCurrentPosL < zzEndReadL {
+					zzInput = zzBufferL[zzCurrentPosL]
+					zzCurrentPosL += 1 //utf8.RuneLen(zzInput)
+				} else if lexer.zzAtEOF {
+					zzInput = YYEOF
+					goto zzForAction
+				} else {
+					// store back cached positions
+					lexer.zzCurrentPos = zzCurrentPosL
+					lexer.zzMarkedPos = zzMarkedPosL
+					eof, err := lexer.zzRefill()
+					if err != nil {
+						return nil, err
+					}
+					// get translated positions and possibly new buffer
+					zzCurrentPosL = lexer.zzCurrentPos
+					zzMarkedPosL = lexer.zzMarkedPos
+					zzBufferL = lexer.zzBuffer
+					zzEndReadL = lexer.zzEndRead
+					if eof {
+						zzInput = YYEOF
+						goto zzForAction
+					} else {
+						zzInput = zzBufferL[zzCurrentPosL]
+						zzCurrentPosL += 1 //utf8.RuneLen(zzInput)
+					}
+				}
+
+				zzNext := zzTransL[zzRowMapL[lexer.zzState]+int(zzCMapL[zzInput])]
+				if zzNext == -1 {
+					goto zzForAction
+				}
+
+				lexer.zzState = zzNext
+
+				zzAttributes = zzAttrL[lexer.zzState]
+				if (zzAttributes & 1) == 1 {
+					zzAction = lexer.zzState
+					zzMarkedPosL = zzCurrentPosL
+					if (zzAttributes & 8) == 8 {
+						goto zzForAction
+					}
+				}
+
+			}
+		}
+
+	zzForAction:
+		// store back cached Position
+		lexer.zzMarkedPos = zzMarkedPosL
+
+		if zzInput == YYEOF && lexer.zzStartRead == lexer.zzCurrentPos {
+			lexer.zzAtEOF = true
+			switch lexer.zzLexicalState {
+			case xc:
+				{
+					lexer.debug("<xc><<EOF>>")
+
+					lexer.yybegin(YYINITIAL)
+					lexer.yyerror("unterminated /* comment")
+				}
+			case 105:
+			case xq:
+				{
+					lexer.debug("<xq><<EOF>>")
+
+					lexer.yybegin(YYINITIAL)
+					lexer.yyerror("unterminated quoted string")
+				}
+				fallthrough
+			case 106:
+			case xdq:
+				{
+					lexer.debug("<xdq><<EOF>>")
+
+					lexer.yybegin(YYINITIAL)
+					lexer.yyerror("unterminated quoted identifier")
+				}
+				fallthrough
+			case 107:
+			case xbin:
+				{
+					lexer.debug("<xbin><<EOF>>")
+
+					lexer.yybegin(YYINITIAL)
+					lexer.yyerror("unterminated binary string literal")
+				}
+				fallthrough
+			case 108:
+			case xhex:
+				{
+					lexer.debug("<xhex><<EOF>>")
+
+					lexer.yybegin(YYINITIAL)
+					lexer.yyerror("unterminated hexadecimal integer")
+				}
+				fallthrough
+			case 109:
+			case xq2:
+				{
+					lexer.yybegin(YYINITIAL)
+					lexer.yyerror("unterminated q2 string")
+				}
+				fallthrough
+			case 110:
+			case xq2_2:
+				{
+					lexer.yybegin(YYINITIAL)
+					lexer.yyerror("unterminated q2 string")
+				}
+				fallthrough
+			case 111:
+			default:
+				return nil, nil
+			}
+		} else {
+			var action int
+			if zzAction < 0 {
+				action = zzAction
+			} else {
+				action = ZZ_ACTION[zzAction]
+			}
+			switch action {
+			case 1:
+				{
+					lexer.debug("{other}")
+
+					return newLVal(lexer.yytext(), NORMAL), nil
+				}
+				fallthrough
+			case 44:
+			case 2:
+				{
+					lexer.debug("{xq_start}")
+
+					lexer.yybegin(xq)
+					lexer.ltstr = ""
+				}
+				fallthrough
+			case 45:
+			case 3:
+				{
+					lexer.debug("{xdq_start}")
+
+					lexer.yybegin(xdq)
+					lexer.ltstr = ""
+					lexer.ltstr += lexer.yytext()
+				}
+				fallthrough
+			case 46:
+			case 4:
+				{
+					lexer.debug("{self} | {op_chars}")
+
+					return newLVal(lexer.yytext(), NORMAL), nil
+				}
+				fallthrough
+			case 47:
+			case 5:
+				{
+					lexer.debug("{identifier}")
+
+					return newLVal(lexer.yytext(), NORMAL), nil
+				}
+				fallthrough
+			case 48:
+			case 6:
+				{
+					lexer.debug("{integer}")
+
+					return newLVal(lexer.yytext(), INT), nil
+				}
+				fallthrough
+			case 49:
+			case 7:
+				{
+					lexer.debug("{whitespace} | {comment} | {c_line_comment}")
+
+					return newLVal(lexer.yytext(), WHITESPACE_OR_COMMENT), nil
+				}
+				fallthrough
+			case 50:
+			case 8:
+				{
+					lexer.debug("<xc>{xc_inside}")
+
+					lexer.ltstr += lexer.yytext()
+				}
+				fallthrough
+			case 51:
+			case 9:
+				{
+					lexer.debug("<xc>[\\/] | <xc>[\\*]")
+
+					lexer.ltstr += lexer.yytext()
+				}
+				fallthrough
+			case 52:
+			case 10:
+				{
+					lexer.debug("<xq>{xq_inside}")
+
+					lexer.ltstr += lexer.yytext()
+				}
+				fallthrough
+			case 53:
+			case 11:
+				{
+					lexer.debug("<xq>{xq_stop}")
+
+					lexer.yybegin(YYINITIAL)
+					return newLVal(lexer.ltstr, STRING), nil
+				}
+				fallthrough
+			case 54:
+			case 12:
+				{
+					lexer.debug("<xdq>{xdq_inside}")
+
+					lexer.ltstr += lexer.yytext()
+				}
+				fallthrough
+			case 55:
+			case 13:
+				{
+					lexer.debug("<xdq>{xdq_stop}")
+
+					lexer.yybegin(YYINITIAL)
+					lexer.ltstr += lexer.yytext()
+					return newLVal(lexer.ltstr, NORMAL), nil
+				}
+				fallthrough
+			case 56:
+			case 14:
+				{
+					lexer.debug("<xbin>{xbin_inside}")
+
+					lexer.ltstr += lexer.yytext()
+				}
+				fallthrough
+			case 57:
+			case 15:
+				{
+					lexer.debug("<xbin>{xbin_stop}")
+
+					lexer.yybegin(YYINITIAL)
+					lexer.ltstr += lexer.yytext()
+					return newLVal(lexer.ltstr, NORMAL), nil
+				}
+				fallthrough
+			case 58:
+			case 16:
+				{
+					lexer.debug("<xhex>{xhex_inside}")
+
+					lexer.ltstr += lexer.yytext()
+				}
+				fallthrough
+			case 59:
+			case 17:
+				{
+					lexer.debug("<xhex>{xhex_stop}")
+
+					lexer.yybegin(YYINITIAL)
+					lexer.ltstr += lexer.yytext()
+					return newLVal(lexer.ltstr, NORMAL), nil
+				}
+				fallthrough
+			case 60:
+			case 18:
+				{
+					lexer.ltstr += lexer.yytext()
+				}
+				fallthrough
+			case 61:
+			case 19:
+				{
+					lexer.yybegin(xq2_2)
+				}
+				fallthrough
+			case 62:
+			case 20:
+				{
+					lexer.ltstr += "]"
+					lexer.ltstr += lexer.yytext()
+					lexer.yybegin(xq2)
+				}
+				fallthrough
+			case 63:
+			case 21:
+				{
+					lexer.yybegin(YYINITIAL)
+
+					return newLVal(lexer.ltstr, STRING), nil
+				}
+				fallthrough
+			case 64:
+			case 22:
+				{
+					lexer.ltstr += "]"
+					lexer.yybegin(xq2_2)
+				}
+				fallthrough
+			case 65:
+			case 23:
+				{
+					lexer.debug("{xc_start}")
+
+					lexer.yybegin(xc)
+					lexer.ltstr = lexer.yytext()
+				}
+				fallthrough
+			case 66:
+			case 24:
+				{
+					lexer.debug("{xbin_start}")
+
+					lexer.yybegin(xbin)
+					lexer.ltstr = ""
+					lexer.ltstr += lexer.yytext()
+				}
+				fallthrough
+			case 67:
+			case 25:
+				{
+					lexer.debug("{xhex_start}")
+
+					lexer.yybegin(xhex)
+					lexer.ltstr = ""
+					lexer.ltstr += lexer.yytext()
+				}
+				fallthrough
+			case 68:
+			case 26:
+				{
+					lexer.debug("{decimal}")
+
+					return newLVal(lexer.yytext(), DECIMAL), nil
+				}
+				fallthrough
+			case 69:
+			case 27:
+				{
+					lexer.debug("{real}")
+
+					return newLVal(lexer.yytext(), DOUBLE), nil
+				}
+				fallthrough
+			case 70:
+			case 28:
+				{
+					lexer.debug("{assign}")
+
+					return newLVal(lexer.yytext(), NORMAL), nil
+				}
+				fallthrough
+			case 71:
+			case 29:
+				{
+					lexer.debug("{selstar}")
+
+					return newLVal(lexer.yytext(), NORMAL), nil
+				}
+				fallthrough
+			case 72:
+			case 30:
+				{
+					lexer.debug("{boundary}")
+
+					return newLVal(lexer.yytext(), NORMAL), nil
+				}
+				fallthrough
+			case 73:
+			case 31:
+				{
+					lexer.debug("<xc>{xc_start}")
+
+					lexer.ltstr += lexer.yytext()
+				}
+				fallthrough
+			case 74:
+			case 32:
+				{
+					lexer.debug("<xc>{xc_stop}")
+
+					lexer.yybegin(YYINITIAL)
+					lexer.ltstr += lexer.yytext()
+					return newLVal(lexer.ltstr, WHITESPACE_OR_COMMENT), nil
+				}
+				fallthrough
+			case 75:
+			case 33:
+				{
+					lexer.debug("<xq>{xq_double}")
+
+					lexer.ltstr += "\\'"
+				}
+				fallthrough
+			case 76:
+			case 34:
+				{ // keep original string
+					lexer.debug("<xdq>{xdq_double}")
+
+					lexer.ltstr += lexer.yytext()
+				}
+				fallthrough
+			case 77:
+			case 35:
+				{
+					lexer.yybegin(xq2)
+					lexer.ltstr = ""
+				}
+				fallthrough
+			case 78:
+			case 36:
+				{
+					lexer.debug("{integer_with_boundary}")
+
+					return newLVal(lexer.yytext(), NORMAL), nil
+				}
+				fallthrough
+			case 79:
+			case 37:
+				{
+					lexer.debug("{hex_integer}")
+
+					return newLVal(lexer.yytext(), HEX_INT), nil
+				}
+				fallthrough
+			case 80:
+			case 38:
+				{
+					lexer.debug("<xq>{xq_cat}")
+				}
+				fallthrough
+			case 81:
+			case 39:
+				{ /* ignore */
+					lexer.debug("<xbin>{xbin_cat}")
+				}
+				fallthrough
+			case 82:
+			case 40:
+				{
+					lexer.debug("<xhex>{xhex_cat}")
+				}
+				fallthrough
+			case 83:
+			case 41:
+				{
+					lexer.debug("{null}")
+
+					return newLVal("null", NULL), nil
+				}
+				fallthrough
+			case 84:
+			case 42:
+				{
+					lexer.debug("{is_null}")
+
+					return newLVal(lexer.yytext(), NORMAL), nil
+				}
+				fallthrough
+			case 85:
+			case 43:
+				{
+					lexer.debug("{not_null}")
+
+					return newLVal(lexer.yytext(), NORMAL), nil
+				}
+				fallthrough
+			case 86:
+			default:
+				lexer.zzScanError(ZZ_NO_MATCH)
+			}
+		}
+	}
+}

+ 1451 - 0
q.go

@@ -0,0 +1,1451 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"database/sql/driver"
+	"math"
+	"strconv"
+	"strings"
+
+	"gitee.com/chunanyong/dm/util"
+)
+
+const (
+	LOADPREC_DEFAULT = 2
+
+	LOADPREC_MAX = 9
+
+	SECDPREC_DEFAULT = 6
+
+	SECDPREC_MAX = 6
+
+	QUA_D byte = 3
+
+	QUA_DH byte = 4
+
+	QUA_DHM byte = 5
+
+	QUA_DHMS byte = 6
+
+	QUA_H byte = 7
+
+	QUA_HM byte = 8
+
+	QUA_HMS byte = 9
+
+	QUA_M byte = 10
+
+	QUA_MS byte = 11
+
+	QUA_S byte = 12
+)
+
+type DmIntervalDT struct {
+	_type byte
+
+	leadScale int
+
+	secScale int
+
+	negative bool
+
+	days int
+
+	hours int
+
+	minutes int
+
+	seconds int
+
+	fraction int
+
+	scaleForSvr int
+
+	Valid bool
+}
+
+func (dt *DmIntervalDT) init() {
+	dt._type = QUA_D
+	dt.leadScale = 2
+	dt.secScale = 6
+	dt.negative = false
+	dt.days = 0
+	dt.hours = 0
+	dt.minutes = 0
+	dt.seconds = 0
+	dt.fraction = 0
+	dt.scaleForSvr = 0
+	dt.Valid = true
+}
+
+func newDmIntervalDTByBytes(bytes []byte) *DmIntervalDT {
+	dt := new(DmIntervalDT)
+	dt.init()
+
+	dt._type = bytes[21]
+	dt.scaleForSvr = int(Dm_build_1.Dm_build_103(bytes, 20))
+	dt.leadScale = (dt.scaleForSvr >> 4) & 0x0000000F
+	dt.secScale = dt.scaleForSvr & 0x0000000F
+
+	switch dt._type {
+	case QUA_D:
+		dt.days = int(Dm_build_1.Dm_build_103(bytes, 0))
+	case QUA_DH:
+		dt.days = int(Dm_build_1.Dm_build_103(bytes, 0))
+		dt.hours = int(Dm_build_1.Dm_build_103(bytes, 4))
+	case QUA_DHM:
+		dt.days = int(Dm_build_1.Dm_build_103(bytes, 0))
+		dt.hours = int(Dm_build_1.Dm_build_103(bytes, 4))
+		dt.minutes = int(Dm_build_1.Dm_build_103(bytes, 8))
+	case QUA_DHMS:
+		dt.days = int(Dm_build_1.Dm_build_103(bytes, 0))
+		dt.hours = int(Dm_build_1.Dm_build_103(bytes, 4))
+		dt.minutes = int(Dm_build_1.Dm_build_103(bytes, 8))
+		dt.seconds = int(Dm_build_1.Dm_build_103(bytes, 12))
+		dt.fraction = int(Dm_build_1.Dm_build_103(bytes, 16))
+	case QUA_H:
+		dt.hours = int(Dm_build_1.Dm_build_103(bytes, 4))
+	case QUA_HM:
+		dt.hours = int(Dm_build_1.Dm_build_103(bytes, 4))
+		dt.minutes = int(Dm_build_1.Dm_build_103(bytes, 8))
+	case QUA_HMS:
+		dt.hours = int(Dm_build_1.Dm_build_103(bytes, 4))
+		dt.minutes = int(Dm_build_1.Dm_build_103(bytes, 8))
+		dt.seconds = int(Dm_build_1.Dm_build_103(bytes, 12))
+		dt.fraction = int(Dm_build_1.Dm_build_103(bytes, 16))
+	case QUA_M:
+		dt.minutes = int(Dm_build_1.Dm_build_103(bytes, 8))
+	case QUA_MS:
+		dt.minutes = int(Dm_build_1.Dm_build_103(bytes, 8))
+		dt.seconds = int(Dm_build_1.Dm_build_103(bytes, 12))
+		dt.fraction = int(Dm_build_1.Dm_build_103(bytes, 16))
+	case QUA_S:
+		dt.seconds = int(Dm_build_1.Dm_build_103(bytes, 12))
+		dt.fraction = int(Dm_build_1.Dm_build_103(bytes, 16))
+	}
+	if dt.days < 0 {
+		dt.days = -dt.days
+		dt.negative = true
+	}
+	if dt.hours < 0 {
+		dt.hours = -dt.hours
+		dt.negative = true
+	}
+	if dt.minutes < 0 {
+		dt.minutes = -dt.minutes
+		dt.negative = true
+	}
+	if dt.seconds < 0 {
+		dt.seconds = -dt.seconds
+		dt.negative = true
+	}
+	if dt.fraction < 0 {
+		dt.fraction = -dt.fraction
+		dt.negative = true
+	}
+
+	return dt
+}
+
+func NewDmIntervalDTByString(str string) (dt *DmIntervalDT, err error) {
+	defer func() {
+		if p := recover(); p != nil {
+			err = ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+	}()
+	dt = new(DmIntervalDT)
+	dt.init()
+
+	if str == "" {
+		return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+	}
+
+	leadStr := strings.TrimSpace(strings.ToUpper(str))
+
+	if !(strings.Index(leadStr, "INTERVAL ") == 0) {
+		return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+	}
+
+	leadStr = strings.TrimSpace(leadStr[strings.Index(leadStr, " "):])
+
+	endIndex := 0
+	var valueStr string
+
+	if endIndex = strings.Index(leadStr[1:], "'"); leadStr[0] == '\'' && endIndex != -1 {
+		endIndex += 1
+		valueStr = strings.TrimSpace(leadStr[1:endIndex])
+		valueStr = dt.checkSign(valueStr)
+		leadStr = strings.TrimSpace(leadStr[endIndex+1:])
+	}
+
+	if valueStr == "" {
+		leadStr = dt.checkSign(leadStr)
+		if endIndex = strings.Index(leadStr[1:], "'"); leadStr[0] != '\'' || endIndex == -1 {
+			return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+		endIndex += 1
+		valueStr = strings.TrimSpace(leadStr[1:endIndex])
+		leadStr = strings.TrimSpace(leadStr[endIndex+1:])
+	}
+
+	strLeadPrec := ""
+	strSecPrec := ""
+
+	leadPrecIndex := 0
+	secPrecIndex := 0
+	toIndex := 0
+
+	if leadPrecIndex = strings.Index(leadStr, "DAY"); leadPrecIndex != -1 {
+		toIndex = strings.Index(leadStr[leadPrecIndex:], "TO")
+
+		if toIndex == -1 {
+			strLeadPrec = strings.TrimSpace(leadStr[leadPrecIndex:])
+			if err := dt.setDay(valueStr); err != nil {
+				return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+			}
+		} else {
+			toIndex += leadPrecIndex
+			strLeadPrec = strings.TrimSpace(leadStr[leadPrecIndex:toIndex])
+
+			if strings.Index(leadStr[toIndex:], "HOUR") != -1 {
+				if err := dt.setDayToHour(valueStr); err != nil {
+					return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+				}
+			} else if strings.Index(leadStr[toIndex:], "MINUTE") != -1 {
+				if err := dt.setDayToMinute(valueStr); err != nil {
+					return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+				}
+			} else if secPrecIndex = strings.Index(leadStr[toIndex:], "SECOND"); secPrecIndex != -1 {
+				secPrecIndex += toIndex
+				strSecPrec = leadStr[secPrecIndex:]
+				if err := dt.setDayToSecond(valueStr); err != nil {
+					return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+				}
+			} else {
+				return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+			}
+		}
+
+		if err := dt.setPrecForSvr(leadStr, strLeadPrec, strSecPrec); err != nil {
+			return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+		return dt, nil
+	}
+
+	if leadPrecIndex = strings.Index(leadStr, "HOUR"); leadPrecIndex != -1 {
+		toIndex = strings.Index(leadStr[leadPrecIndex:], "TO")
+
+		if toIndex == -1 {
+			toIndex += leadPrecIndex
+			strLeadPrec = leadStr[leadPrecIndex:]
+			if err := dt.setHour(valueStr); err != nil {
+				return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+			}
+		} else {
+			strLeadPrec = leadStr[leadPrecIndex:toIndex]
+
+			if strings.Index(leadStr[toIndex:], "MINUTE") != -1 {
+				if err := dt.setHourToMinute(valueStr); err != nil {
+					return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+				}
+			} else if secPrecIndex = strings.Index(leadStr[toIndex:], "SECOND"); secPrecIndex != -1 {
+				secPrecIndex += toIndex
+				strSecPrec = leadStr[secPrecIndex:]
+				if err := dt.setHourToSecond(valueStr); err != nil {
+					return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+				}
+			} else {
+				return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+			}
+		}
+
+		if err := dt.setPrecForSvr(leadStr, strLeadPrec, strSecPrec); err != nil {
+			return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+		return dt, nil
+	}
+
+	if leadPrecIndex = strings.Index(leadStr, "MINUTE"); leadPrecIndex != -1 {
+		toIndex = strings.Index(leadStr, "TO")
+
+		if toIndex == -1 {
+			toIndex += leadPrecIndex
+			strLeadPrec = leadStr[leadPrecIndex:]
+			if err := dt.setMinute(valueStr); err != nil {
+				return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+			}
+		} else {
+			strLeadPrec = leadStr[leadPrecIndex:toIndex]
+
+			if secPrecIndex = strings.Index(leadStr[toIndex:], "SECOND"); secPrecIndex != -1 {
+				strSecPrec = leadStr[secPrecIndex:]
+				if err := dt.setMinuteToSecond(valueStr); err != nil {
+					return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+				}
+			} else {
+				return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+			}
+		}
+
+		if err := dt.setPrecForSvr(leadStr, strLeadPrec, strSecPrec); err != nil {
+			return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+		return dt, nil
+	}
+
+	if leadPrecIndex = strings.Index(leadStr, "SECOND"); leadPrecIndex != -1 {
+		if err := dt.setSecond(valueStr); err != nil {
+			return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+
+		leadStr = strings.TrimSpace(leadStr[leadPrecIndex:])
+
+		colonIndex := strings.Index(leadStr, ",")
+		if colonIndex != -1 {
+			strLeadPrec = strings.TrimSpace(leadStr[:colonIndex]) + ")"
+			strSecPrec = "(" + strings.TrimSpace(leadStr[:colonIndex+1])
+		}
+
+		if err := dt.setPrecForSvr(leadStr, strLeadPrec, strSecPrec); err != nil {
+			return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+		return dt, nil
+	}
+
+	return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+}
+
+func (dt *DmIntervalDT) GetDay() int {
+	return dt.days
+}
+
+func (dt *DmIntervalDT) GetHour() int {
+	return dt.hours
+}
+
+func (dt *DmIntervalDT) GetMinute() int {
+	return dt.minutes
+}
+
+func (dt *DmIntervalDT) GetSecond() int {
+	return dt.seconds
+}
+
+func (dt *DmIntervalDT) GetMsec() int {
+	return dt.fraction
+}
+
+func (dt *DmIntervalDT) GetDTType() byte {
+	return dt._type
+}
+
+func (dt *DmIntervalDT) String() string {
+	if !dt.Valid {
+		return ""
+	}
+	var l, destLen int
+	var dStr, hStr, mStr, sStr, nStr string
+	interval := "INTERVAL "
+
+	switch dt._type {
+	case QUA_D:
+		dStr := strconv.FormatInt(int64(float64(dt.days)), 10)
+		if dt.negative {
+			interval += "-"
+		}
+
+		if len(dStr) < dt.leadScale {
+			l = len(dStr)
+			destLen = dt.leadScale
+
+			for destLen > l {
+				dStr = "0" + dStr
+				destLen--
+			}
+		}
+
+		interval += "'" + dStr + "' DAY(" + strconv.FormatInt(int64(dt.leadScale), 10) + ")"
+	case QUA_DH:
+		dStr = strconv.FormatInt(int64(float64(dt.days)), 10)
+		hStr = strconv.FormatInt(int64(float64(dt.hours)), 10)
+
+		if dt.negative {
+			interval += "-"
+		}
+
+		if len(dStr) < dt.leadScale {
+			l = len(dStr)
+			destLen = dt.leadScale
+
+			for destLen > l {
+				dStr = "0" + dStr
+				destLen--
+			}
+		}
+
+		if len(hStr) < 2 {
+			hStr = "0" + hStr
+		}
+
+		interval += "'" + dStr + " " + hStr + "' DAY(" + strconv.FormatInt(int64(dt.leadScale), 10) + ") TO HOUR"
+	case QUA_DHM:
+		dStr = strconv.FormatInt(int64(float64(dt.days)), 10)
+		hStr = strconv.FormatInt(int64(float64(dt.hours)), 10)
+		mStr = strconv.FormatInt(int64(float64(dt.minutes)), 10)
+
+		if dt.negative {
+			interval += "-"
+		}
+
+		if len(dStr) < dt.leadScale {
+			l = len(dStr)
+			destLen = dt.leadScale
+
+			for destLen > l {
+				dStr = "0" + dStr
+				destLen--
+			}
+		}
+		if len(hStr) < 2 {
+			hStr = "0" + hStr
+		}
+		if len(mStr) < 2 {
+			mStr = "0" + mStr
+		}
+		interval += "'" + dStr + " " + hStr + ":" + mStr + "' DAY(" + strconv.FormatInt(int64(dt.leadScale), 10) + ") TO MINUTE"
+	case QUA_DHMS:
+		dStr = strconv.FormatInt(int64(float64(dt.days)), 10)
+		hStr = strconv.FormatInt(int64(float64(dt.hours)), 10)
+		mStr = strconv.FormatInt(int64(float64(dt.minutes)), 10)
+		sStr = strconv.FormatInt(int64(float64(dt.seconds)), 10)
+		nStr = dt.getMsecString()
+		if dt.negative {
+			interval += "-"
+		}
+
+		if len(dStr) < dt.leadScale {
+			l = len(dStr)
+			destLen = dt.leadScale
+
+			for destLen > l {
+				dStr = "0" + dStr
+				destLen--
+			}
+		}
+		if len(hStr) < 2 {
+			hStr = "0" + hStr
+		}
+		if len(mStr) < 2 {
+			mStr = "0" + mStr
+		}
+		if len(sStr) < 2 {
+			sStr = "0" + sStr
+		}
+		interval += "'" + dStr + " " + hStr + ":" + mStr + ":" + sStr
+		if nStr != "" {
+			interval += "." + nStr
+		}
+
+		interval += "' DAY(" + strconv.FormatInt(int64(dt.leadScale), 10) + ") TO SECOND(" + strconv.FormatInt(int64(dt.secScale), 10) + ")"
+	case QUA_H:
+		hStr = strconv.FormatInt(int64(float64(dt.hours)), 10)
+		if dt.negative {
+			interval += "-"
+		}
+
+		if len(hStr) < dt.leadScale {
+			l = len(hStr)
+			destLen = dt.leadScale
+
+			for destLen > l {
+				hStr = "0" + hStr
+				destLen--
+			}
+		}
+
+		interval += "'" + hStr + "' HOUR(" + strconv.FormatInt(int64(dt.leadScale), 10) + ")"
+	case QUA_HM:
+		hStr = strconv.FormatInt(int64(float64(dt.hours)), 10)
+		mStr = strconv.FormatInt(int64(float64(dt.minutes)), 10)
+
+		if dt.negative {
+			interval += "-"
+		}
+
+		if len(hStr) < dt.leadScale {
+			l = len(hStr)
+			destLen = dt.leadScale
+
+			for destLen > l {
+				hStr = "0" + hStr
+				destLen--
+			}
+		}
+		if len(mStr) < 2 {
+			mStr = "0" + mStr
+		}
+
+		interval += "'" + hStr + ":" + mStr + "' HOUR(" + strconv.FormatInt(int64(dt.leadScale), 10) + ") TO MINUTE"
+	case QUA_HMS:
+		nStr = dt.getMsecString()
+		hStr = strconv.FormatInt(int64(float64(dt.hours)), 10)
+		mStr = strconv.FormatInt(int64(float64(dt.minutes)), 10)
+		sStr = strconv.FormatInt(int64(float64(dt.seconds)), 10)
+
+		if dt.negative {
+			interval += "-"
+		}
+
+		if len(hStr) < dt.leadScale {
+			l = len(hStr)
+			destLen = dt.leadScale
+
+			for destLen > l {
+				hStr = "0" + hStr
+				destLen--
+			}
+		}
+		if len(mStr) < 2 {
+			mStr = "0" + mStr
+		}
+		if len(sStr) < 2 {
+			sStr = "0" + sStr
+		}
+
+		interval += "'" + hStr + ":" + mStr + ":" + sStr
+		if nStr != "" {
+			interval += "." + nStr
+		}
+
+		interval += "' HOUR(" + strconv.FormatInt(int64(dt.leadScale), 10) + ") TO SECOND(" + strconv.FormatInt(int64(dt.secScale), 10) + ")"
+
+	case QUA_M:
+		mStr = strconv.FormatInt(int64(float64(dt.minutes)), 10)
+
+		if dt.negative {
+			interval += "-"
+		}
+
+		if len(mStr) < dt.leadScale {
+			l = len(mStr)
+			destLen = dt.leadScale
+
+			for destLen > l {
+				mStr = "0" + mStr
+				destLen--
+			}
+		}
+
+		interval += "'" + mStr + "' MINUTE(" + strconv.FormatInt(int64(dt.leadScale), 10) + ")"
+	case QUA_MS:
+		nStr = dt.getMsecString()
+		mStr = strconv.FormatInt(int64(float64(dt.minutes)), 10)
+		sStr = strconv.FormatInt(int64(float64(dt.seconds)), 10)
+
+		if dt.negative {
+			interval += "-"
+		}
+
+		if len(mStr) < dt.leadScale {
+			l = len(mStr)
+			destLen = dt.leadScale
+
+			for destLen > l {
+				mStr = "0" + mStr
+				destLen--
+			}
+		}
+		if len(sStr) < 2 {
+			sStr = "0" + sStr
+		}
+		interval += "'" + mStr + ":" + sStr
+		if nStr != "" {
+			interval += "." + nStr
+		}
+
+		interval += "' MINUTE(" + strconv.FormatInt(int64(dt.leadScale), 10) + ") TO SECOND(" + strconv.FormatInt(int64(dt.secScale), 10) + ")"
+	case QUA_S:
+		nStr = dt.getMsecString()
+		sStr = strconv.FormatInt(int64(float64(dt.seconds)), 10)
+
+		if dt.negative {
+			interval += "-"
+		}
+
+		if len(sStr) < dt.leadScale {
+			l = len(sStr)
+			destLen = dt.leadScale
+
+			for destLen > l {
+				sStr = "0" + sStr
+				destLen--
+			}
+		}
+
+		interval += "'" + sStr
+
+		if nStr != "" {
+			interval += "." + nStr
+		}
+
+		interval += "' SECOND(" + strconv.FormatInt(int64(dt.leadScale), 10) + ", " + strconv.FormatInt(int64(dt.secScale), 10) + ")"
+
+	}
+
+	return interval
+}
+
+func (dest *DmIntervalDT) Scan(src interface{}) error {
+	if dest == nil {
+		return ECGO_STORE_IN_NIL_POINTER.throw()
+	}
+	switch src := src.(type) {
+	case nil:
+		*dest = *new(DmIntervalDT)
+
+		(*dest).Valid = false
+		return nil
+	case *DmIntervalDT:
+		*dest = *src
+		return nil
+	case string:
+		ret, err := NewDmIntervalDTByString(src)
+		if err != nil {
+			return err
+		}
+		*dest = *ret
+		return nil
+	default:
+		return UNSUPPORTED_SCAN
+	}
+}
+
+func (dt DmIntervalDT) Value() (driver.Value, error) {
+	if !dt.Valid {
+		return nil, nil
+	}
+	return dt, nil
+}
+
+func (dt *DmIntervalDT) checkScale(leadScale int) (int, error) {
+	switch dt._type {
+	case QUA_D:
+		if leadScale == -1 {
+			leadScale = len(strconv.FormatInt(int64(math.Abs(float64(dt.days))), 10))
+		} else if leadScale < len(strconv.FormatInt(int64(math.Abs(float64(dt.days))), 10)) {
+			return 0, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+
+	case QUA_DH:
+		if leadScale == -1 {
+			leadScale = len(strconv.FormatInt(int64(math.Abs(float64(dt.days))), 10))
+		} else if leadScale < len(strconv.FormatInt(int64(math.Abs(float64(dt.days))), 10)) {
+			return 0, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+
+		if int64(math.Abs(float64((dt.hours)))) > 23 {
+			return 0, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+
+	case QUA_DHM:
+		if leadScale == -1 {
+			leadScale = len(strconv.FormatInt(int64(math.Abs(float64(dt.days))), 10))
+		} else if leadScale < len(strconv.FormatInt(int64(math.Abs(float64(dt.days))), 10)) {
+			return 0, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+		if int64(math.Abs(float64(dt.hours))) > 23 || int64(math.Abs(float64(dt.minutes))) > 59 {
+			return 0, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+
+	case QUA_DHMS:
+		if leadScale == -1 {
+			leadScale = len(strconv.FormatInt(int64(math.Abs(float64(dt.days))), 10))
+		} else if leadScale < len(strconv.FormatInt(int64(math.Abs(float64(dt.days))), 10)) {
+			return 0, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+		if int64(math.Abs(float64(dt.hours))) > 23 || int64(math.Abs(float64(dt.minutes))) > 59 ||
+			int64(math.Abs(float64(dt.seconds))) > 59 {
+			return 0, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+
+	case QUA_H:
+		if leadScale == -1 {
+			leadScale = len(strconv.FormatInt(int64(math.Abs(float64(dt.hours))), 10))
+		} else if leadScale < len(strconv.FormatInt(int64(math.Abs(float64(dt.hours))), 10)) {
+			return 0, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+
+	case QUA_HM:
+		if leadScale == -1 {
+			leadScale = len(strconv.FormatInt(int64(math.Abs(float64(dt.hours))), 10))
+		} else if leadScale < len(strconv.FormatInt(int64(math.Abs(float64(dt.hours))), 10)) {
+			return 0, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+		if int64(math.Abs(float64(dt.minutes))) > 59 {
+			return 0, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+
+	case QUA_HMS:
+		if leadScale == -1 {
+			leadScale = len(strconv.FormatInt(int64(math.Abs(float64(dt.hours))), 10))
+		} else if leadScale < len(strconv.FormatInt(int64(math.Abs(float64(dt.hours))), 10)) {
+			return 0, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+		if int64(math.Abs(float64(dt.minutes))) > 59 || int64(math.Abs(float64(dt.seconds))) > 59 {
+			return 0, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+
+	case QUA_M:
+		if leadScale == -1 {
+			leadScale = len(strconv.FormatInt(int64(math.Abs(float64(dt.minutes))), 10))
+		} else if leadScale < len(strconv.FormatInt(int64(math.Abs(float64(dt.minutes))), 10)) {
+			return 0, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+
+	case QUA_MS:
+		if leadScale == -1 {
+			leadScale = len(strconv.FormatInt(int64(math.Abs(float64(dt.minutes))), 10))
+		} else if leadScale < len(strconv.FormatInt(int64(math.Abs(float64(dt.minutes))), 10)) {
+			return 0, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+		if int64(math.Abs(float64(dt.seconds))) > 59 {
+			return 0, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+	case QUA_S:
+		if leadScale == -1 {
+			leadScale = len(strconv.FormatInt(int64(math.Abs(float64(dt.minutes))), 10))
+		} else if leadScale < len(strconv.FormatInt(int64(math.Abs(float64(dt.minutes))), 10)) {
+			return 0, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+	}
+
+	if leadScale > LOADPREC_MAX {
+		return 0, ECGO_INVALID_TIME_INTERVAL.throw()
+	}
+	return leadScale, nil
+}
+
+func (dt *DmIntervalDT) parsePrec(leadStr string) (int, error) {
+	leftBtId := strings.Index(leadStr, "(")
+	rightBtId := strings.Index(leadStr, ")")
+	var prec int64 = -1
+
+	if rightBtId != -1 && leftBtId != -1 && rightBtId > leftBtId+1 {
+		strPrec := strings.TrimSpace(leadStr[leftBtId+1 : rightBtId])
+		var err error
+		prec, err = strconv.ParseInt(strPrec, 10, 32)
+		if err != nil {
+			return -1, err
+		}
+	}
+
+	return int(prec), nil
+}
+
+func (dt *DmIntervalDT) setPrecForSvr(fullStr string, leadScale string, secScale string) error {
+	prec, err := dt.parsePrec(leadScale)
+	if err != nil {
+		return err
+	}
+
+	prec, err = dt.checkScale(prec)
+	if err != nil {
+		return err
+	}
+
+	if prec < LOADPREC_DEFAULT {
+		dt.leadScale = LOADPREC_DEFAULT
+	} else {
+		dt.leadScale = prec
+	}
+
+	prec, err = dt.parsePrec(secScale)
+	if err != nil {
+		return err
+	}
+
+	if prec >= 0 && prec < SECDPREC_MAX {
+		dt.secScale = prec
+	} else {
+		dt.secScale = SECDPREC_DEFAULT
+	}
+
+	dt.scaleForSvr = (int(dt._type) << 8) + (dt.leadScale << 4) + dt.secScale
+	return nil
+}
+
+func (dt *DmIntervalDT) checkSign(str string) string {
+
+	if str[0] == '-' {
+		str = strings.TrimSpace(str[1:])
+		dt.negative = true
+	} else if str[0] == '+' {
+		str = strings.TrimSpace(str[1:])
+		dt.negative = false
+	}
+
+	return str
+}
+
+func (dt *DmIntervalDT) setDay(value string) error {
+	list := util.Split(value, " :.")
+	if len(list) > 1 {
+		return ECGO_INVALID_TIME_INTERVAL.throw()
+	}
+	dt._type = QUA_D
+	i, err := strconv.ParseInt(value, 10, 32)
+	if err != nil {
+		return err
+	}
+
+	if i < 0 {
+		dt.days = int(-i)
+		dt.negative = true
+	} else {
+		dt.days = int(i)
+	}
+	return nil
+}
+
+func (dt *DmIntervalDT) setHour(value string) error {
+	list := util.Split(value, " :.")
+	if len(list) > 1 {
+		return ECGO_INVALID_TIME_INTERVAL.throw()
+	}
+	dt._type = QUA_H
+	i, err := strconv.ParseInt(value, 10, 32)
+	if err != nil {
+		return err
+	}
+
+	if i < 0 {
+		dt.hours = int(-i)
+		dt.negative = true
+	} else {
+		dt.hours = int(i)
+	}
+	return nil
+}
+
+func (dt *DmIntervalDT) setMinute(value string) error {
+	list := util.Split(value, " :.")
+	if len(list) > 1 {
+		return ECGO_INVALID_TIME_INTERVAL.throw()
+	}
+	dt._type = QUA_M
+	i, err := strconv.ParseInt(value, 10, 32)
+	if err != nil {
+		return err
+	}
+
+	if i < 0 {
+		dt.minutes = int(-i)
+		dt.negative = true
+	} else {
+		dt.minutes = int(i)
+	}
+	return nil
+}
+
+func (dt *DmIntervalDT) setSecond(value string) error {
+	list := util.Split(value, " :.")
+	if len(list) > 2 {
+		return ECGO_INVALID_TIME_INTERVAL.throw()
+	}
+	dt._type = QUA_S
+	i, err := strconv.ParseInt(list[0], 10, 32)
+	if err != nil {
+		return err
+	}
+
+	nano := 0
+	if len(list) > 1 {
+		strNano := "0" + "." + list[1]
+		d_v, err := strconv.ParseFloat(strNano, 64)
+		if err != nil {
+			return err
+		}
+		nx := math.Pow10(dt.secScale)
+		nano = (int)(d_v * nx)
+	}
+
+	if i < 0 {
+		dt.seconds = int(-i)
+	} else {
+		dt.seconds = int(i)
+	}
+	if nano < 0 {
+		dt.fraction = -nano
+	} else {
+		dt.fraction = nano
+	}
+	if i < 0 || nano < 0 {
+		dt.negative = true
+	}
+	return nil
+
+}
+
+func (dt *DmIntervalDT) setHourToSecond(value string) error {
+	list := util.Split(value, " :.")
+	if len(list) > 4 {
+		return ECGO_INVALID_TIME_INTERVAL.throw()
+	}
+	dt._type = QUA_HMS
+
+	h, err := strconv.ParseInt(list[0], 10, 32)
+	if err != nil {
+		return err
+	}
+
+	m, err := strconv.ParseInt(list[1], 10, 32)
+	if err != nil {
+		return err
+	}
+
+	s, err := strconv.ParseInt(list[2], 10, 32)
+	if err != nil {
+		return err
+	}
+	nano := 0
+	if len(list) > 3 {
+		strNano := "0" + "." + list[3]
+		d_v, err := strconv.ParseFloat(strNano, 64)
+		if err != nil {
+			return err
+		}
+		nx := math.Pow10(dt.secScale)
+		nano = (int)(d_v * nx)
+	}
+
+	if h < 0 {
+		dt.hours = int(-h)
+	} else {
+		dt.hours = int(h)
+	}
+	if m < 0 {
+		dt.minutes = int(-m)
+	} else {
+		dt.minutes = int(m)
+	}
+	if s < 0 {
+		dt.seconds = int(-s)
+	} else {
+		dt.seconds = int(s)
+	}
+	if nano < 0 {
+		dt.fraction = -nano
+	} else {
+		dt.fraction = nano
+	}
+	if h < 0 || m < 0 || s < 0 || nano < 0 {
+		dt.negative = true
+	}
+	return nil
+}
+
+func (dt *DmIntervalDT) setHourToMinute(value string) error {
+	value = strings.TrimSpace(value)
+	list := util.Split(value, " :.")
+	if len(list) > 2 {
+		return ECGO_INVALID_TIME_INTERVAL.throw()
+	}
+	dt._type = QUA_HM
+
+	h, err := strconv.ParseInt(list[0], 10, 32)
+	if err != nil {
+		return err
+	}
+
+	m, err := strconv.ParseInt(list[1], 10, 32)
+	if err != nil {
+		return err
+	}
+
+	if h < 0 {
+		dt.hours = int(-h)
+	} else {
+		dt.hours = int(h)
+	}
+	if m < 0 {
+		dt.minutes = int(-m)
+	} else {
+		dt.minutes = int(m)
+	}
+	if h < 0 || m < 0 {
+		dt.negative = true
+	}
+	return nil
+}
+
+func (dt *DmIntervalDT) setMinuteToSecond(value string) error {
+	list := util.Split(value, " :.")
+	if len(list) > 3 {
+		return ECGO_INVALID_TIME_INTERVAL.throw()
+	}
+	dt._type = QUA_MS
+
+	m, err := strconv.ParseInt(list[0], 10, 32)
+	if err != nil {
+		return err
+	}
+
+	s, err := strconv.ParseInt(list[1], 10, 32)
+	if err != nil {
+		return err
+	}
+
+	nano := 0
+	if len(list) > 2 {
+		strNano := "0" + "." + list[2]
+		d_v, err := strconv.ParseFloat(strNano, 64)
+		if err != nil {
+			return err
+		}
+
+		nx := math.Pow10(dt.secScale)
+		nano = (int)(d_v * nx)
+	}
+
+	if m < 0 {
+		dt.minutes = int(-m)
+	} else {
+		dt.minutes = int(m)
+	}
+	if s < 0 {
+		dt.seconds = int(-s)
+	} else {
+		dt.seconds = int(s)
+	}
+	if nano < 0 {
+		dt.fraction = -nano
+	} else {
+		dt.fraction = nano
+	}
+	if m < 0 || s < 0 || nano < 0 {
+		dt.negative = true
+	}
+	return nil
+}
+
+func (dt *DmIntervalDT) setDayToHour(value string) error {
+	list := util.Split(value, " :.")
+	if len(list) > 2 {
+		return ECGO_INVALID_TIME_INTERVAL.throw()
+	}
+	dt._type = QUA_DH
+
+	d, err := strconv.ParseInt(list[0], 10, 32)
+	if err != nil {
+		return err
+	}
+
+	h, err := strconv.ParseInt(list[1], 10, 32)
+	if err != nil {
+		return err
+	}
+
+	if d < 0 {
+		dt.days = int(-d)
+	} else {
+		dt.days = int(d)
+	}
+	if h < 0 {
+		dt.hours = int(-h)
+	} else {
+		dt.hours = int(h)
+	}
+	if d < 0 || h < 0 {
+		dt.negative = true
+	}
+	return nil
+}
+
+func (dt *DmIntervalDT) setDayToMinute(value string) error {
+	list := util.Split(value, " :.")
+	if len(list) > 3 {
+		return ECGO_INVALID_TIME_INTERVAL.throw()
+	}
+	dt._type = QUA_DHM
+
+	d, err := strconv.ParseInt(list[0], 10, 32)
+	if err != nil {
+		return err
+	}
+
+	h, err := strconv.ParseInt(list[1], 10, 32)
+	if err != nil {
+		return err
+	}
+
+	m, err := strconv.ParseInt(list[2], 10, 32)
+	if err != nil {
+		return err
+	}
+
+	if d < 0 {
+		dt.days = int(-d)
+	} else {
+		dt.days = int(d)
+	}
+	if h < 0 {
+		dt.hours = int(-h)
+	} else {
+		dt.hours = int(h)
+	}
+	if m < 0 {
+		dt.minutes = int(-m)
+	} else {
+		dt.minutes = int(m)
+	}
+	if d < 0 || h < 0 || m < 0 {
+		dt.negative = true
+	}
+	return nil
+}
+
+func (dt *DmIntervalDT) setDayToSecond(value string) error {
+	list := util.Split(value, " :.")
+	if len(list) > 5 {
+		return ECGO_INVALID_TIME_INTERVAL.throw()
+	}
+	dt._type = QUA_DHMS
+
+	d, err := strconv.ParseInt(list[0], 10, 32)
+	if err != nil {
+		return err
+	}
+
+	h, err := strconv.ParseInt(list[1], 10, 32)
+	if err != nil {
+		return err
+	}
+
+	m, err := strconv.ParseInt(list[2], 10, 32)
+	if err != nil {
+		return err
+	}
+
+	s, err := strconv.ParseInt(list[3], 10, 32)
+	if err != nil {
+		return err
+	}
+
+	nano := 0
+	if len(list) > 4 {
+		strNano := "0" + "." + list[4]
+		d_v, err := strconv.ParseFloat(strNano, 64)
+		if err != nil {
+			return err
+		}
+
+		nx := math.Pow10(dt.secScale)
+		nano = (int)(d_v * nx)
+	}
+
+	if d < 0 {
+		dt.days = int(-d)
+	} else {
+		dt.days = int(d)
+	}
+	if h < 0 {
+		dt.hours = int(-h)
+	} else {
+		dt.hours = int(h)
+	}
+	if m < 0 {
+		dt.minutes = int(-m)
+	} else {
+		dt.minutes = int(m)
+	}
+	if s < 0 {
+		dt.seconds = int(-s)
+	} else {
+		dt.seconds = int(s)
+	}
+	if nano < 0 {
+		dt.fraction = -nano
+	} else {
+		dt.fraction = nano
+	}
+	if d < 0 || h < 0 || m < 0 || s < 0 || nano < 0 {
+		dt.negative = true
+	}
+	return nil
+}
+
+func (dt *DmIntervalDT) getMsecString() string {
+	nano := strconv.Itoa(dt.fraction)
+
+	for i := 6 - len(nano); i > 0; i-- {
+		nano = "0" + nano
+	}
+
+	if len(nano) > dt.secScale {
+		nano = nano[:dt.secScale]
+	}
+
+	return nano
+}
+
+func (dt *DmIntervalDT) encode(scale int) ([]byte, error) {
+	if scale == 0 {
+		scale = dt.scaleForSvr
+	}
+	day, hour, minute, second, f := dt.days, dt.hours, dt.minutes, dt.seconds, dt.fraction
+	if scale != dt.scaleForSvr {
+		convertDT, err := dt.convertTo(scale)
+		if err != nil {
+			return nil, err
+		}
+		day, hour, minute, second, f = convertDT.days, convertDT.hours, convertDT.minutes, convertDT.seconds, convertDT.fraction
+	} else {
+		loadPrec := (scale >> 4) & 0x0000000F
+		if _, err := dt.checkScale(loadPrec); err != nil {
+			return nil, err
+		}
+	}
+
+	bytes := make([]byte, 24)
+	if dt.negative {
+		Dm_build_1.Dm_build_17(bytes, 0, int32(-day))
+		Dm_build_1.Dm_build_17(bytes, 4, int32(-hour))
+		Dm_build_1.Dm_build_17(bytes, 8, int32(-minute))
+		Dm_build_1.Dm_build_17(bytes, 12, int32(-second))
+		Dm_build_1.Dm_build_17(bytes, 16, int32(-f))
+		Dm_build_1.Dm_build_17(bytes, 20, int32(scale))
+	} else {
+		Dm_build_1.Dm_build_17(bytes, 0, int32(day))
+		Dm_build_1.Dm_build_17(bytes, 4, int32(hour))
+		Dm_build_1.Dm_build_17(bytes, 8, int32(minute))
+		Dm_build_1.Dm_build_17(bytes, 12, int32(second))
+		Dm_build_1.Dm_build_17(bytes, 16, int32(f))
+		Dm_build_1.Dm_build_17(bytes, 20, int32(scale))
+	}
+	return bytes, nil
+}
+
+func (dt *DmIntervalDT) convertTo(scale int) (*DmIntervalDT, error) {
+	destType := (scale & 0x0000FF00) >> 8
+	leadPrec := (scale >> 4) & 0x0000000F
+	secScale := scale & 0x0000000F
+	dayIndex := 0
+	hourIndex := 1
+	minuteIndex := 2
+	secondIndex := 3
+	fractionIndex := 4
+	orgDT := make([]int, 5)
+	destDT := make([]int, 5)
+
+	switch dt._type {
+	case QUA_D:
+		orgDT[dayIndex] = dt.days
+	case QUA_DH:
+		orgDT[dayIndex] = dt.days
+		orgDT[hourIndex] = dt.hours
+	case QUA_DHM:
+		orgDT[dayIndex] = dt.days
+		orgDT[hourIndex] = dt.hours
+		orgDT[minuteIndex] = dt.minutes
+	case QUA_DHMS:
+		orgDT[dayIndex] = dt.days
+		orgDT[hourIndex] = dt.hours
+		orgDT[minuteIndex] = dt.minutes
+		orgDT[secondIndex] = dt.seconds
+		orgDT[fractionIndex] = dt.fraction
+	case QUA_H:
+		orgDT[dayIndex] = dt.hours / 24
+		orgDT[hourIndex] = dt.hours % 24
+	case QUA_HM:
+		orgDT[dayIndex] = dt.hours / 24
+		orgDT[hourIndex] = dt.hours % 24
+		orgDT[minuteIndex] = dt.minutes
+	case QUA_HMS:
+		orgDT[dayIndex] = dt.hours / 24
+		orgDT[hourIndex] = dt.hours % 24
+		orgDT[minuteIndex] = dt.minutes
+		orgDT[secondIndex] = dt.seconds
+		orgDT[fractionIndex] = dt.fraction
+	case QUA_M:
+		orgDT[dayIndex] = dt.minutes / (24 * 60)
+		orgDT[hourIndex] = (dt.minutes % (24 * 60)) / 60
+		orgDT[minuteIndex] = (dt.minutes % (24 * 60)) % 60
+	case QUA_MS:
+		orgDT[dayIndex] = dt.minutes / (24 * 60)
+		orgDT[hourIndex] = (dt.minutes % (24 * 60)) / 60
+		orgDT[minuteIndex] = (dt.minutes % (24 * 60)) % 60
+		orgDT[secondIndex] = dt.seconds
+		orgDT[fractionIndex] = dt.fraction
+	case QUA_S:
+		orgDT[dayIndex] = dt.seconds / (24 * 60 * 60)
+		orgDT[hourIndex] = (dt.seconds % (24 * 60 * 60)) / (60 * 60)
+		orgDT[minuteIndex] = ((dt.seconds % (24 * 60 * 60)) % (60 * 60)) / 60
+		orgDT[secondIndex] = ((dt.seconds % (24 * 60 * 60)) % (60 * 60)) % 60
+		orgDT[fractionIndex] = dt.fraction
+	}
+
+	switch byte(destType) {
+	case QUA_D:
+		destDT[dayIndex] = orgDT[dayIndex]
+		if orgDT[hourIndex] >= 12 {
+			incrementDay(QUA_D, destDT)
+		}
+		if leadPrec < len(strconv.Itoa(int(math.Abs(float64(destDT[dayIndex]))))) {
+			return nil, ECGO_INTERVAL_OVERFLOW.throw()
+		}
+	case QUA_DH:
+		destDT[dayIndex] = orgDT[dayIndex]
+		destDT[hourIndex] = orgDT[hourIndex]
+		if orgDT[minuteIndex] >= 30 {
+			incrementHour(QUA_DH, destDT)
+		}
+		if leadPrec < len(strconv.Itoa(int(math.Abs(float64(destDT[dayIndex]))))) {
+			return nil, ECGO_INTERVAL_OVERFLOW.throw()
+		}
+	case QUA_DHM:
+		destDT[dayIndex] = orgDT[dayIndex]
+		destDT[hourIndex] = orgDT[hourIndex]
+		destDT[minuteIndex] = orgDT[minuteIndex]
+		if orgDT[secondIndex] >= 30 {
+			incrementMinute(QUA_DHM, destDT)
+		}
+		if leadPrec < len(strconv.Itoa(int(math.Abs(float64(destDT[dayIndex]))))) {
+			return nil, ECGO_INTERVAL_OVERFLOW.throw()
+		}
+	case QUA_DHMS:
+		destDT[dayIndex] = orgDT[dayIndex]
+		destDT[hourIndex] = orgDT[hourIndex]
+		destDT[minuteIndex] = orgDT[minuteIndex]
+		destDT[secondIndex] = orgDT[secondIndex]
+		destDT[fractionIndex] = orgDT[fractionIndex]
+		dt.convertMSecond(QUA_DHMS, destDT, secScale)
+		if leadPrec < len(strconv.Itoa(int(math.Abs(float64(destDT[dayIndex]))))) {
+			return nil, ECGO_INTERVAL_OVERFLOW.throw()
+		}
+	case QUA_H:
+		destDT[hourIndex] = orgDT[dayIndex]*24 + orgDT[hourIndex]
+		if orgDT[minuteIndex] >= 30 {
+			incrementHour(QUA_H, destDT)
+		}
+		if leadPrec < len(strconv.Itoa(int(math.Abs(float64(destDT[hourIndex]))))) {
+			return nil, ECGO_INTERVAL_OVERFLOW.throw()
+		}
+	case QUA_HM:
+		destDT[hourIndex] = orgDT[dayIndex]*24 + orgDT[hourIndex]
+		destDT[minuteIndex] = orgDT[minuteIndex]
+		if orgDT[secondIndex] >= 30 {
+			incrementMinute(QUA_HM, destDT)
+		}
+		if leadPrec < len(strconv.Itoa(int(math.Abs(float64(destDT[hourIndex]))))) {
+			return nil, ECGO_INTERVAL_OVERFLOW.throw()
+		}
+	case QUA_HMS:
+		destDT[hourIndex] = orgDT[dayIndex]*24 + orgDT[hourIndex]
+		destDT[minuteIndex] = orgDT[minuteIndex]
+		destDT[secondIndex] = orgDT[secondIndex]
+		destDT[fractionIndex] = orgDT[fractionIndex]
+		dt.convertMSecond(QUA_HMS, destDT, secScale)
+		if leadPrec < len(strconv.Itoa(int(math.Abs(float64(destDT[hourIndex]))))) {
+			return nil, ECGO_INTERVAL_OVERFLOW.throw()
+		}
+	case QUA_M:
+		destDT[minuteIndex] = orgDT[dayIndex]*24*60 + orgDT[hourIndex]*60 + orgDT[minuteIndex]
+		if orgDT[secondIndex] >= 30 {
+			incrementMinute(QUA_M, destDT)
+		}
+		if leadPrec < len(strconv.Itoa(int(math.Abs(float64(destDT[minuteIndex]))))) {
+			return nil, ECGO_INTERVAL_OVERFLOW.throw()
+		}
+	case QUA_MS:
+		destDT[minuteIndex] = orgDT[dayIndex]*24*60 + orgDT[hourIndex]*60 + orgDT[minuteIndex]
+		destDT[secondIndex] = orgDT[secondIndex]
+		destDT[fractionIndex] = orgDT[fractionIndex]
+		dt.convertMSecond(QUA_MS, destDT, secScale)
+		if leadPrec < len(strconv.Itoa(int(math.Abs(float64(destDT[minuteIndex]))))) {
+			return nil, ECGO_INTERVAL_OVERFLOW.throw()
+		}
+	case QUA_S:
+		destDT[secondIndex] = orgDT[dayIndex]*24*60*60 + orgDT[hourIndex]*60*60 + orgDT[minuteIndex]*60 + orgDT[secondIndex]
+		destDT[fractionIndex] = orgDT[fractionIndex]
+		dt.convertMSecond(QUA_S, destDT, secScale)
+		if leadPrec < len(strconv.Itoa(int(math.Abs(float64(destDT[secondIndex]))))) {
+			return nil, ECGO_INTERVAL_OVERFLOW.throw()
+		}
+	}
+
+	return &DmIntervalDT{
+		_type:       byte(destType),
+		negative:    dt.negative,
+		leadScale:   (scale >> 4) & 0x0000000F,
+		secScale:    scale & 0x0000000F,
+		scaleForSvr: scale,
+		days:        destDT[dayIndex],
+		hours:       destDT[hourIndex],
+		minutes:     destDT[minuteIndex],
+		seconds:     destDT[secondIndex],
+		fraction:    destDT[fractionIndex],
+		Valid:       true,
+	}, nil
+}
+
+func (dt DmIntervalDT) convertMSecond(destType byte, destDT []int, destSecScale int) {
+	fractionIndex := 4
+	orgFraction := destDT[fractionIndex]
+	if destSecScale == 0 || destSecScale < dt.secScale {
+		n := int(math.Pow(10, 6-float64(destSecScale)-1))
+		f := orgFraction / n / 10
+
+		if (orgFraction/n)%10 >= 5 {
+			f++
+			f = f * n * 10
+			if f == 1000000 {
+				destDT[fractionIndex] = 0
+				incrementSecond(destType, destDT)
+				return
+			}
+		}
+		destDT[fractionIndex] = f
+	}
+}
+
+func incrementDay(destType byte, dt []int) {
+	dayIndex := 0
+	dt[dayIndex]++
+}
+
+func incrementHour(destType byte, dt []int) {
+	hourIndex := 1
+	dt[hourIndex]++
+	if dt[hourIndex] == 24 && destType < QUA_H {
+		incrementDay(destType, dt)
+		dt[hourIndex] = 0
+	}
+}
+
+func incrementMinute(destType byte, dt []int) {
+	minuteIndex := 2
+	dt[minuteIndex]++
+	if dt[minuteIndex] == 60 && destType < QUA_M {
+		incrementHour(destType, dt)
+		dt[minuteIndex] = 0
+	}
+}
+
+func incrementSecond(destType byte, dt []int) {
+	secondIndex := 3
+	dt[secondIndex]++
+	if dt[secondIndex] == 60 && destType < QUA_S {
+		incrementMinute(destType, dt)
+		dt[secondIndex] = 0
+	}
+}
+
+func (dt *DmIntervalDT) checkValid() error {
+	if !dt.Valid {
+		return ECGO_IS_NULL.throw()
+	}
+	return nil
+}

+ 490 - 0
r.go

@@ -0,0 +1,490 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"database/sql/driver"
+	"math"
+	"strconv"
+	"strings"
+
+	"gitee.com/chunanyong/dm/util"
+)
+
+const (
+	QUA_Y  = 0
+	QUA_YM = 1
+	QUA_MO = 2
+)
+
+type DmIntervalYM struct {
+	leadScale      int
+	isLeadScaleSet bool
+	_type          byte
+	years          int
+	months         int
+	scaleForSvr    int
+
+	Valid bool
+}
+
+func newDmIntervalYM() *DmIntervalYM {
+	return &DmIntervalYM{
+		Valid: true,
+	}
+}
+
+func NewDmIntervalYMByString(str string) (ym *DmIntervalYM, err error) {
+	defer func() {
+		if p := recover(); p != nil {
+			err = ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+	}()
+	ym = newDmIntervalYM()
+	ym.isLeadScaleSet = false
+	if err = ym.parseIntervYMString(strings.TrimSpace(str)); err != nil {
+		return nil, err
+	}
+	return ym, nil
+}
+
+func newDmIntervalYMByBytes(bytes []byte) *DmIntervalYM {
+	ym := newDmIntervalYM()
+
+	ym.scaleForSvr = int(Dm_build_1.Dm_build_103(bytes, 8))
+	ym.leadScale = (ym.scaleForSvr >> 4) & 0x0000000F
+	ym._type = bytes[9]
+	switch ym._type {
+	case QUA_Y:
+		ym.years = int(Dm_build_1.Dm_build_103(bytes, 0))
+	case QUA_YM:
+		ym.years = int(Dm_build_1.Dm_build_103(bytes, 0))
+		ym.months = int(Dm_build_1.Dm_build_103(bytes, 4))
+	case QUA_MO:
+		ym.months = int(Dm_build_1.Dm_build_103(bytes, 4))
+	}
+	return ym
+}
+
+func (ym *DmIntervalYM) GetYear() int {
+	return ym.years
+}
+
+func (ym *DmIntervalYM) GetMonth() int {
+	return ym.months
+}
+
+func (ym *DmIntervalYM) GetYMType() byte {
+	return ym._type
+}
+
+func (ym *DmIntervalYM) String() string {
+	if !ym.Valid {
+		return ""
+	}
+	str := "INTERVAL "
+	var year, month string
+	var l int
+	var destLen int
+
+	switch ym._type {
+	case QUA_Y:
+		year = strconv.FormatInt(int64(math.Abs(float64(ym.years))), 10)
+		if ym.years < 0 {
+			str += "-"
+		}
+
+		if ym.leadScale > len(year) {
+			l = len(year)
+			destLen = ym.leadScale
+
+			for destLen > l {
+				year = "0" + year
+				destLen--
+			}
+		}
+
+		str += "'" + year + "' YEAR(" + strconv.FormatInt(int64(ym.leadScale), 10) + ")"
+	case QUA_YM:
+		year = strconv.FormatInt(int64(math.Abs(float64(ym.years))), 10)
+		month = strconv.FormatInt(int64(math.Abs(float64(ym.months))), 10)
+
+		if ym.years < 0 || ym.months < 0 {
+			str += "-"
+		}
+
+		if ym.leadScale > len(year) {
+			l = len(year)
+			destLen = ym.leadScale
+
+			for destLen > l {
+				year = "0" + year
+				destLen--
+			}
+		}
+
+		if len(month) < 2 {
+			month = "0" + month
+		}
+
+		str += "'" + year + "-" + month + "' YEAR(" + strconv.FormatInt(int64(ym.leadScale), 10) + ") TO MONTH"
+	case QUA_MO:
+
+		month = strconv.FormatInt(int64(math.Abs(float64(ym.months))), 10)
+		if ym.months < 0 {
+			str += "-"
+		}
+
+		if ym.leadScale > len(month) {
+			l = len(month)
+			destLen = ym.leadScale
+			for destLen > l {
+				month = "0" + month
+				destLen--
+			}
+		}
+
+		str += "'" + month + "' MONTH(" + strconv.FormatInt(int64(ym.leadScale), 10) + ")"
+	}
+	return str
+}
+
+func (dest *DmIntervalYM) Scan(src interface{}) error {
+	if dest == nil {
+		return ECGO_STORE_IN_NIL_POINTER.throw()
+	}
+	switch src := src.(type) {
+	case nil:
+		*dest = *new(DmIntervalYM)
+
+		(*dest).Valid = false
+		return nil
+	case *DmIntervalYM:
+		*dest = *src
+		return nil
+	case string:
+		ret, err := NewDmIntervalYMByString(src)
+		if err != nil {
+			return err
+		}
+		*dest = *ret
+		return nil
+	default:
+		return UNSUPPORTED_SCAN
+	}
+}
+
+func (ym DmIntervalYM) Value() (driver.Value, error) {
+	if !ym.Valid {
+		return nil, nil
+	}
+	return ym, nil
+}
+
+func (ym *DmIntervalYM) parseIntervYMString(str string) error {
+	str = strings.ToUpper(str)
+	ret := strings.Split(str, " ")
+	l := len(ret)
+	if l < 3 || !util.StringUtil.EqualsIgnoreCase(ret[0], "INTERVAL") || !(strings.HasPrefix(ret[2], "YEAR") || strings.HasPrefix(ret[2], "MONTH")) {
+		return ECGO_INVALID_TIME_INTERVAL.throw()
+	}
+	ym._type = QUA_YM
+	yearId := strings.Index(str, "YEAR")
+	monthId := strings.Index(str, "MONTH")
+	toId := strings.Index(str, "TO")
+	var err error
+	if toId == -1 {
+		if yearId != -1 && monthId == -1 {
+			ym._type = QUA_Y
+			ym.leadScale, err = ym.getLeadPrec(str, yearId)
+			if err != nil {
+				return err
+			}
+		} else if monthId != -1 && yearId == -1 {
+			ym._type = QUA_MO
+			ym.leadScale, err = ym.getLeadPrec(str, monthId)
+			if err != nil {
+				return err
+			}
+		} else {
+			return ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+	} else {
+		if yearId == -1 || monthId == -1 {
+			return ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+		ym._type = QUA_YM
+		ym.leadScale, err = ym.getLeadPrec(str, yearId)
+		if err != nil {
+			return err
+		}
+	}
+
+	ym.scaleForSvr = (int(ym._type) << 8) + (ym.leadScale << 4)
+	timeVals, err := ym.getTimeValue(ret[1], int(ym._type))
+	if err != nil {
+		return err
+	}
+	ym.years = timeVals[0]
+	ym.months = timeVals[1]
+	return ym.checkScale(ym.leadScale)
+}
+
+func (ym *DmIntervalYM) getLeadPrec(str string, startIndex int) (int, error) {
+	if ym.isLeadScaleSet {
+		return ym.leadScale, nil
+	}
+
+	leftBtId := strings.Index(str[startIndex:], "(")
+	rightBtId := strings.Index(str[startIndex:], ")")
+	leadPrec := 0
+
+	if rightBtId == -1 && leftBtId == -1 {
+		leftBtId += startIndex
+		rightBtId += startIndex
+		l := strings.Index(str, "'")
+		var r int
+		var dataStr string
+		if l != -1 {
+			r = strings.Index(str[l+1:], "'")
+			if r != -1 {
+				r += l + 1
+			}
+		} else {
+			r = -1
+		}
+
+		if r != -1 {
+			dataStr = strings.TrimSpace(str[l+1 : r])
+		} else {
+			dataStr = ""
+		}
+
+		if dataStr != "" {
+			sign := dataStr[0]
+			if sign == '+' || sign == '-' {
+				dataStr = strings.TrimSpace(dataStr[1:])
+			}
+			end := strings.Index(dataStr, "-")
+
+			if end != -1 {
+				dataStr = dataStr[:end]
+			}
+
+			leadPrec = len(dataStr)
+		} else {
+			leadPrec = 2
+		}
+	} else if rightBtId != -1 && leftBtId != -1 && rightBtId > leftBtId+1 {
+		leftBtId += startIndex
+		rightBtId += startIndex
+		strPrec := strings.TrimSpace(str[leftBtId+1 : rightBtId])
+		temp, err := strconv.ParseInt(strPrec, 10, 32)
+		if err != nil {
+			return 0, err
+		}
+
+		leadPrec = int(temp)
+	} else {
+		return 0, ECGO_INVALID_TIME_INTERVAL.throw()
+	}
+
+	return leadPrec, nil
+}
+
+func (ym *DmIntervalYM) checkScale(prec int) error {
+	switch ym._type {
+	case QUA_Y:
+		if prec < len(strconv.FormatInt(int64(math.Abs(float64(ym.years))), 10)) {
+			return ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+	case QUA_YM:
+		if prec < len(strconv.FormatInt(int64(math.Abs(float64(ym.years))), 10)) {
+			return ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+
+		if int64(math.Abs(float64(ym.months))) > 11 {
+			return ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+
+	case QUA_MO:
+		if prec < len(strconv.FormatInt(int64(math.Abs(float64(ym.months))), 10)) {
+			return ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+	}
+	return nil
+}
+
+func (ym *DmIntervalYM) getTimeValue(subStr string, _type int) ([]int, error) {
+	hasQuate := false
+	if subStr[0] == '\'' && subStr[len(subStr)-1] == '\'' {
+		hasQuate = true
+		subStr = strings.TrimSpace(subStr[1 : len(subStr)-1])
+	}
+
+	negative := false
+	if strings.Index(subStr, "-") == 0 {
+		negative = true
+		subStr = subStr[1:]
+	} else if strings.Index(subStr, "+") == 0 {
+		negative = false
+		subStr = subStr[1:]
+	}
+
+	if subStr[0] == '\'' && subStr[len(subStr)-1] == '\'' {
+		hasQuate = true
+		subStr = strings.TrimSpace(subStr[1 : len(subStr)-1])
+	}
+
+	if !hasQuate {
+		return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+	}
+
+	lastSignIndex := strings.LastIndex(subStr, "-")
+
+	list := make([]string, 2)
+	if lastSignIndex == -1 || lastSignIndex == 0 {
+		list[0] = subStr
+		list[1] = ""
+	} else {
+		list[0] = subStr[0:lastSignIndex]
+		list[1] = subStr[lastSignIndex+1:]
+	}
+
+	var yearVal, monthVal int64
+	var err error
+	if ym._type == QUA_YM {
+		yearVal, err = strconv.ParseInt(list[0], 10, 32)
+		if err != nil {
+			return nil, err
+		}
+
+		if util.StringUtil.EqualsIgnoreCase(list[1], "") {
+			monthVal = 0
+		} else {
+			monthVal, err = strconv.ParseInt(list[1], 10, 32)
+			if err != nil {
+				return nil, err
+			}
+		}
+
+		if negative {
+			yearVal *= -1
+			monthVal *= -1
+		}
+
+		if yearVal > int64(math.Pow10(ym.leadScale))-1 || yearVal < 1-int64(math.Pow10(ym.leadScale)) {
+			return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+	} else if ym._type == QUA_Y {
+		yearVal, err = strconv.ParseInt(list[0], 10, 32)
+		if err != nil {
+			return nil, err
+		}
+		monthVal = 0
+
+		if negative {
+			yearVal *= -1
+		}
+
+		if yearVal > int64(math.Pow10(ym.leadScale))-1 || yearVal < 1-int64(math.Pow10(ym.leadScale)) {
+			return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+	} else {
+		yearVal = 0
+		monthVal, err = strconv.ParseInt(list[0], 10, 32)
+		if err != nil {
+			return nil, err
+		}
+		if negative {
+			monthVal *= -1
+		}
+
+		if monthVal > int64(math.Pow10(ym.leadScale))-1 || monthVal < 1-int64(math.Pow10(ym.leadScale)) {
+			return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+	}
+
+	ret := make([]int, 2)
+	ret[0] = int(yearVal)
+	ret[1] = int(monthVal)
+
+	return ret, nil
+}
+
+func (ym *DmIntervalYM) encode(scale int) ([]byte, error) {
+	if scale == 0 {
+		scale = ym.scaleForSvr
+	}
+	year, month := ym.years, ym.months
+	if err := ym.checkScale(ym.leadScale); err != nil {
+		return nil, err
+	}
+	if scale != ym.scaleForSvr {
+		convertYM, err := ym.convertTo(scale)
+		if err != nil {
+			return nil, err
+		}
+		year = convertYM.years
+		month = convertYM.months
+	} else {
+		if err := ym.checkScale(ym.leadScale); err != nil {
+			return nil, err
+		}
+	}
+
+	bytes := make([]byte, 12)
+	Dm_build_1.Dm_build_17(bytes, 0, int32(year))
+	Dm_build_1.Dm_build_17(bytes, 4, int32(month))
+	Dm_build_1.Dm_build_17(bytes, 8, int32(scale))
+	return bytes, nil
+}
+
+func (ym *DmIntervalYM) convertTo(scale int) (*DmIntervalYM, error) {
+	destType := (scale & 0x0000FF00) >> 8
+	leadPrec := (scale >> 4) & 0x0000000F
+	totalMonths := ym.years*12 + ym.months
+	year := 0
+	month := 0
+	switch destType {
+	case QUA_Y:
+		year = totalMonths / 12
+
+		if totalMonths%12 >= 6 {
+			year++
+		} else if totalMonths%12 <= -6 {
+			year--
+		}
+		if leadPrec < len(strconv.Itoa(int(math.Abs(float64(year))))) {
+			return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+	case QUA_YM:
+		year = totalMonths / 12
+		month = totalMonths % 12
+		if leadPrec < len(strconv.Itoa(int(math.Abs(float64(year))))) {
+			return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+	case QUA_MO:
+		month = totalMonths
+		if leadPrec < len(strconv.Itoa(int(math.Abs(float64(month))))) {
+			return nil, ECGO_INVALID_TIME_INTERVAL.throw()
+		}
+	}
+	return &DmIntervalYM{
+		_type:       byte(destType),
+		years:       year,
+		months:      month,
+		scaleForSvr: scale,
+		leadScale:   (scale >> 4) & 0x0000000F,
+		Valid:       true,
+	}, nil
+}
+
+func (ym *DmIntervalYM) checkValid() error {
+	if !ym.Valid {
+		return ECGO_IS_NULL.throw()
+	}
+	return nil
+}

+ 54 - 0
s.go

@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+type DmResult struct {
+	filterable
+	dmStmt       *DmStatement
+	affectedRows int64
+	insertId     int64
+}
+
+func newDmResult(bs *DmStatement, execInfo *execRetInfo) *DmResult {
+	result := DmResult{}
+	result.resetFilterable(&bs.filterable)
+	result.dmStmt = bs
+	result.affectedRows = execInfo.updateCount
+	result.insertId = execInfo.lastInsertId
+	result.idGenerator = dmResultIDGenerator
+
+	return &result
+}
+
+/*************************************************************
+ ** PUBLIC METHODS AND FUNCTIONS
+ *************************************************************/
+func (r *DmResult) LastInsertId() (int64, error) {
+	//if err := r.dmStmt.checkClosed(); err != nil {
+	//	return -1, err
+	//}
+	if len(r.filterChain.filters) == 0 {
+		return r.lastInsertId()
+	}
+	return r.filterChain.reset().DmResultLastInsertId(r)
+}
+
+func (r *DmResult) RowsAffected() (int64, error) {
+	//if err := r.dmStmt.checkClosed(); err != nil {
+	//	return -1, err
+	//}
+	if len(r.filterChain.filters) == 0 {
+		return r.rowsAffected()
+	}
+	return r.filterChain.reset().DmResultRowsAffected(r)
+}
+
+func (result *DmResult) lastInsertId() (int64, error) {
+	return result.insertId, nil
+}
+
+func (result *DmResult) rowsAffected() (int64, error) {
+	return result.affectedRows, nil
+}

+ 30 - 0
security/zy.go

@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+//  This is a mirror of golang.org/x/crypto/internal/subtle.
+package security
+
+import "unsafe"
+
+// AnyOverlap reports whether x and y share memory at any (not necessarily
+// corresponding) index. The memory beyond the slice length is ignored.
+func AnyOverlap(x, y []byte) bool {
+	return len(x) > 0 && len(y) > 0 &&
+		uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) &&
+		uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1]))
+}
+
+// InexactOverlap reports whether x and y share memory at any non-corresponding
+// index. The memory beyond the slice length is ignored. Note that x and y can
+// have different lengths and still not have any inexact overlap.
+//
+// InexactOverlap can be used to implement the requirements of the crypto/cipher
+// AEAD, Block, BlockMode and Stream interfaces.
+func InexactOverlap(x, y []byte) bool {
+	if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] {
+		return false
+	}
+	return AnyOverlap(x, y)
+}

+ 11 - 0
security/zz.go

@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package security
+
+type Cipher interface {
+	Encrypt(plaintext []byte, genDigest bool) []byte
+	Decrypt(ciphertext []byte, checkDigest bool) ([]byte, error)
+}

+ 87 - 0
security/zza.go

@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package security
+
+import (
+	"crypto/rand"
+	"errors"
+	"io"
+	"math/big"
+)
+
+type dhGroup struct {
+	p *big.Int
+	g *big.Int
+}
+
+func newDhGroup(prime, generator *big.Int) *dhGroup {
+	return &dhGroup{
+		p: prime,
+		g: generator,
+	}
+}
+
+func (dg *dhGroup) P() *big.Int {
+	p := new(big.Int)
+	p.Set(dg.p)
+	return p
+}
+
+func (dg *dhGroup) G() *big.Int {
+	g := new(big.Int)
+	g.Set(dg.g)
+	return g
+}
+
+// 生成本地公私钥
+func (dg *dhGroup) GeneratePrivateKey(randReader io.Reader) (key *DhKey, err error) {
+	if randReader == nil {
+		randReader = rand.Reader
+	}
+	// 0 < x < p
+	x, err := rand.Int(randReader, dg.p)
+	if err != nil {
+		return
+	}
+	zero := big.NewInt(0)
+	for x.Cmp(zero) == 0 {
+		x, err = rand.Int(randReader, dg.p)
+		if err != nil {
+			return
+		}
+	}
+	key = new(DhKey)
+	key.x = x
+
+	// y = g ^ x mod p
+	key.y = new(big.Int).Exp(dg.g, x, dg.p)
+	key.group = dg
+	return
+}
+
+func (dg *dhGroup) ComputeKey(pubkey *DhKey, privkey *DhKey) (kye *DhKey, err error) {
+	if dg.p == nil {
+		err = errors.New("DH: invalid group")
+		return
+	}
+	if pubkey.y == nil {
+		err = errors.New("DH: invalid public key")
+		return
+	}
+	if pubkey.y.Sign() <= 0 || pubkey.y.Cmp(dg.p) >= 0 {
+		err = errors.New("DH parameter out of bounds")
+		return
+	}
+	if privkey.x == nil {
+		err = errors.New("DH: invalid private key")
+		return
+	}
+	k := new(big.Int).Exp(pubkey.y, privkey.x, dg.p)
+	key := new(DhKey)
+	key.y = k
+	key.group = dg
+	return
+}

+ 64 - 0
security/zzb.go

@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package security
+
+import "math/big"
+
+type DhKey struct {
+	x     *big.Int
+	y     *big.Int
+	group *dhGroup
+}
+
+func newPublicKey(s []byte) *DhKey {
+	key := new(DhKey)
+	key.y = new(big.Int).SetBytes(s)
+	return key
+}
+
+func (dk *DhKey) GetX() *big.Int {
+	x := new(big.Int)
+	x.Set(dk.x)
+	return x
+}
+
+func (dk *DhKey) GetY() *big.Int {
+	y := new(big.Int)
+	y.Set(dk.y)
+	return y
+}
+
+func (dk *DhKey) GetYBytes() []byte {
+	if dk.y == nil {
+		return nil
+	}
+	if dk.group != nil {
+		blen := (dk.group.p.BitLen() + 7) / 8
+		ret := make([]byte, blen)
+		copyWithLeftPad(ret, dk.y.Bytes())
+		return ret
+	}
+	return dk.y.Bytes()
+}
+
+func (dk *DhKey) GetYString() string {
+	if dk.y == nil {
+		return ""
+	}
+	return dk.y.String()
+}
+
+func (dk *DhKey) IsPrivateKey() bool {
+	return dk.x != nil
+}
+
+func copyWithLeftPad(dest, src []byte) {
+	numPaddingBytes := len(dest) - len(src)
+	for i := 0; i < numPaddingBytes; i++ {
+		dest[i] = 0
+	}
+	copy(dest[:numPaddingBytes], src)
+}

+ 69 - 0
security/zzc.go

@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+// go官方没有实现ecb加密模式
+package security
+
+import (
+	"crypto/cipher"
+)
+
+type ecb struct {
+	b         cipher.Block
+	blockSize int
+}
+
+func newECB(b cipher.Block) *ecb {
+	return &ecb{
+		b:         b,
+		blockSize: b.BlockSize(),
+	}
+}
+
+type ecbEncrypter ecb
+
+func NewECBEncrypter(b cipher.Block) cipher.BlockMode {
+	return (*ecbEncrypter)(newECB(b))
+}
+
+func (x *ecbEncrypter) BlockSize() int { return x.blockSize }
+
+func (x *ecbEncrypter) CryptBlocks(dst, src []byte) {
+	if len(src)%x.blockSize != 0 {
+		panic("dm/security: input not full blocks")
+	}
+	if len(dst) < len(src) {
+		panic("dm/security: output smaller than input")
+	}
+	if InexactOverlap(dst[:len(src)], src) {
+		panic("dm/security: invalid buffer overlap")
+	}
+	for bs, be := 0, x.blockSize; bs < len(src); bs, be = bs+x.blockSize, be+x.blockSize {
+		x.b.Encrypt(dst[bs:be], src[bs:be])
+	}
+}
+
+type ecbDecrypter ecb
+
+func NewECBDecrypter(b cipher.Block) cipher.BlockMode {
+	return (*ecbDecrypter)(newECB(b))
+}
+
+func (x *ecbDecrypter) BlockSize() int { return x.blockSize }
+
+func (x *ecbDecrypter) CryptBlocks(dst, src []byte) {
+	if len(src)%x.blockSize != 0 {
+		panic("dm/security: input not full blocks")
+	}
+	if len(dst) < len(src) {
+		panic("dm/security: output smaller than input")
+	}
+	if InexactOverlap(dst[:len(src)], src) {
+		panic("dm/security: invalid buffer overlap")
+	}
+	for bs, be := 0, x.blockSize; bs < len(src); bs, be = bs+x.blockSize, be+x.blockSize {
+		x.b.Decrypt(dst[bs:be], src[bs:be])
+	}
+}

+ 114 - 0
security/zzd.go

@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package security
+
+import (
+	"math/big"
+)
+
+const (
+	DH_KEY_LENGTH int = 64
+	/* 低7位用于保存分组加密算法中的工作模式 */
+	WORK_MODE_MASK int = 0x007f
+	ECB_MODE       int = 0x1
+	CBC_MODE       int = 0x2
+	CFB_MODE       int = 0x4
+	OFB_MODE       int = 0x8
+	/* 高位保存加密算法 */
+	ALGO_MASK int = 0xff80
+	DES       int = 0x0080
+	DES3      int = 0x0100
+	AES128    int = 0x0200
+	AES192    int = 0x0400
+	AES256    int = 0x0800
+	RC4       int = 0x1000
+	MD5       int = 0x1100
+
+	// 用户名密码加密算法
+	DES_CFB int = 132
+	// 消息加密摘要长度
+	MD5_DIGEST_SIZE int = 16
+
+	MIN_EXTERNAL_CIPHER_ID int = 5000
+)
+
+var dhParaP = "C009D877BAF5FAF416B7F778E6115DCB90D65217DCC2F08A9DFCB5A192C593EBAB02929266B8DBFC2021039FDBD4B7FDE2B996E00008F57AE6EFB4ED3F17B6D3"
+var dhParaG = "5"
+var defaultIV = []byte{0x20, 0x21, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
+	0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a,
+	0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x20}
+var p *big.Int
+var g *big.Int
+
+func NewClientKeyPair() (key *DhKey, err error) {
+	p, _ = new(big.Int).SetString(dhParaP, 16)
+	g, _ = new(big.Int).SetString(dhParaG, 16)
+	dhGroup := newDhGroup(p, g)
+	key, err = dhGroup.GeneratePrivateKey(nil)
+	if err != nil {
+		return nil, err
+	}
+	return key, nil
+}
+
+func ComputeSessionKey(clientPrivKey *DhKey, serverPubKey []byte) []byte {
+	serverKeyX := bytes2Bn(serverPubKey)
+	clientPrivKeyX := clientPrivKey.GetX()
+	sessionKeyBN := serverKeyX.Exp(serverKeyX, clientPrivKeyX, p)
+	return Bn2Bytes(sessionKeyBN, 0)
+}
+
+func bytes2Bn(bnBytesSrc []byte) *big.Int {
+	if bnBytesSrc == nil {
+		return nil
+	}
+	if bnBytesSrc[0] == 0 {
+		return new(big.Int).SetBytes(bnBytesSrc)
+	}
+	validBytesCount := len(bnBytesSrc) + 1
+	bnBytesTo := make([]byte, validBytesCount)
+	bnBytesTo[0] = 0
+	copy(bnBytesTo[1:validBytesCount], bnBytesSrc)
+	return new(big.Int).SetBytes(bnBytesTo)
+}
+
+func Bn2Bytes(bn *big.Int, bnLen int) []byte {
+	var bnBytesSrc, bnBytesTemp, bnBytesTo []byte
+	var leading_zero_count int
+	validBytesCount := 0
+	if bn == nil {
+		return nil
+	}
+	bnBytesSrc = bn.Bytes()
+
+	// 去除首位0
+	if bnBytesSrc[0] != 0 {
+		bnBytesTemp = bnBytesSrc
+		validBytesCount = len(bnBytesTemp)
+	} else {
+		validBytesCount = len(bnBytesSrc) - 1
+		bnBytesTemp = make([]byte, validBytesCount)
+		copy(bnBytesTemp, bnBytesSrc[1:validBytesCount+1])
+	}
+
+	if bnLen == 0 {
+		leading_zero_count = 0
+	} else {
+		leading_zero_count = bnLen - validBytesCount
+	}
+	// 如果位数不足DH_KEY_LENGTH则在前面补0
+	if leading_zero_count > 0 {
+		bnBytesTo = make([]byte, DH_KEY_LENGTH)
+		i := 0
+		for i = 0; i < leading_zero_count; i++ {
+			bnBytesTo[i] = 0
+		}
+		copy(bnBytesTo[i:i+validBytesCount], bnBytesTemp)
+	} else {
+		bnBytesTo = bnBytesTemp
+	}
+	return bnBytesTo
+}

+ 211 - 0
security/zze.go

@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package security
+
+import (
+	"bytes"
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/des"
+	"crypto/md5"
+	"crypto/rc4"
+	"errors"
+	"reflect"
+)
+
+type SymmCipher struct {
+	encryptCipher interface{} //cipher.BlockMode | cipher.Stream
+	decryptCipher interface{} //cipher.BlockMode | cipher.Stream
+	key           []byte
+	block         cipher.Block // 分组加密算法
+	algorithmType int
+	workMode      int
+	needPadding   bool
+}
+
+func NewSymmCipher(algorithmID int, key []byte) (SymmCipher, error) {
+	var sc SymmCipher
+	var err error
+	sc.key = key
+	sc.algorithmType = algorithmID & ALGO_MASK
+	sc.workMode = algorithmID & WORK_MODE_MASK
+	switch sc.algorithmType {
+	case AES128:
+		if sc.block, err = aes.NewCipher(key[:16]); err != nil {
+			return sc, err
+		}
+	case AES192:
+		if sc.block, err = aes.NewCipher(key[:24]); err != nil {
+			return sc, err
+		}
+	case AES256:
+		if sc.block, err = aes.NewCipher(key[:32]); err != nil {
+			return sc, err
+		}
+	case DES:
+		if sc.block, err = des.NewCipher(key[:8]); err != nil {
+			return sc, err
+		}
+	case DES3:
+		var tripleDESKey []byte
+		tripleDESKey = append(tripleDESKey, key[:16]...)
+		tripleDESKey = append(tripleDESKey, key[:8]...)
+		if sc.block, err = des.NewTripleDESCipher(tripleDESKey); err != nil {
+			return sc, err
+		}
+	case RC4:
+		if sc.encryptCipher, err = rc4.NewCipher(key[:16]); err != nil {
+			return sc, err
+		}
+		if sc.decryptCipher, err = rc4.NewCipher(key[:16]); err != nil {
+			return sc, err
+		}
+		return sc, nil
+	default:
+		return sc, errors.New("invalidCipher")
+	}
+	blockSize := sc.block.BlockSize()
+	if sc.encryptCipher, err = sc.getEncrypter(sc.workMode, sc.block, defaultIV[:blockSize]); err != nil {
+		return sc, err
+	}
+	if sc.decryptCipher, err = sc.getDecrypter(sc.workMode, sc.block, defaultIV[:blockSize]); err != nil {
+		return sc, err
+	}
+	return sc, nil
+}
+
+func (sc SymmCipher) Encrypt(plaintext []byte, genDigest bool) []byte {
+	// 执行过加密后,IV值变了,需要重新初始化encryptCipher对象(因为没有类似resetIV的方法)
+	if sc.algorithmType != RC4 {
+		sc.encryptCipher, _ = sc.getEncrypter(sc.workMode, sc.block, defaultIV[:sc.block.BlockSize()])
+	} else {
+		sc.encryptCipher, _ = rc4.NewCipher(sc.key[:16])
+	}
+	// 填充
+	var paddingtext = make([]byte, len(plaintext))
+	copy(paddingtext, plaintext)
+	if sc.needPadding {
+		paddingtext = pkcs5Padding(paddingtext)
+	}
+
+	ret := make([]byte, len(paddingtext))
+
+	if v, ok := sc.encryptCipher.(cipher.Stream); ok {
+		v.XORKeyStream(ret, paddingtext)
+	} else if v, ok := sc.encryptCipher.(cipher.BlockMode); ok {
+		v.CryptBlocks(ret, paddingtext)
+	}
+
+	// md5摘要
+	if genDigest {
+		digest := md5.Sum(plaintext)
+		encrypt := ret
+		ret = make([]byte, len(encrypt)+len(digest))
+		copy(ret[:len(encrypt)], encrypt)
+		copy(ret[len(encrypt):], digest[:])
+	}
+	return ret
+}
+
+func (sc SymmCipher) Decrypt(ciphertext []byte, checkDigest bool) ([]byte, error) {
+	// 执行过解密后,IV值变了,需要重新初始化decryptCipher对象(因为没有类似resetIV的方法)
+	if sc.algorithmType != RC4 {
+		sc.decryptCipher, _ = sc.getDecrypter(sc.workMode, sc.block, defaultIV[:sc.block.BlockSize()])
+	} else {
+		sc.decryptCipher, _ = rc4.NewCipher(sc.key[:16])
+	}
+	var ret []byte
+	if checkDigest {
+		var digest = ciphertext[len(ciphertext)-MD5_DIGEST_SIZE:]
+		ret = ciphertext[:len(ciphertext)-MD5_DIGEST_SIZE]
+		ret = sc.decrypt(ret)
+		var msgDigest = md5.Sum(ret)
+		if !reflect.DeepEqual(msgDigest[:], digest) {
+			return nil, errors.New("Decrypt failed/Digest not match\n")
+		}
+	} else {
+		ret = sc.decrypt(ciphertext)
+	}
+	return ret, nil
+}
+
+func (sc SymmCipher) decrypt(ciphertext []byte) []byte {
+	ret := make([]byte, len(ciphertext))
+	if v, ok := sc.decryptCipher.(cipher.Stream); ok {
+		v.XORKeyStream(ret, ciphertext)
+	} else if v, ok := sc.decryptCipher.(cipher.BlockMode); ok {
+		v.CryptBlocks(ret, ciphertext)
+	}
+	// 去除填充
+	if sc.needPadding {
+		ret = pkcs5UnPadding(ret)
+	}
+	return ret
+}
+
+func (sc *SymmCipher) getEncrypter(workMode int, block cipher.Block, iv []byte) (ret interface{}, err error) {
+	switch workMode {
+	case ECB_MODE:
+		ret = NewECBEncrypter(block)
+		sc.needPadding = true
+	case CBC_MODE:
+		ret = cipher.NewCBCEncrypter(block, iv)
+		sc.needPadding = true
+	case CFB_MODE:
+		ret = cipher.NewCFBEncrypter(block, iv)
+		sc.needPadding = false
+	case OFB_MODE:
+		ret = cipher.NewOFB(block, iv)
+		sc.needPadding = false
+	default:
+		err = errors.New("invalidCipherMode")
+	}
+	return
+}
+
+func (sc *SymmCipher) getDecrypter(workMode int, block cipher.Block, iv []byte) (ret interface{}, err error) {
+	switch workMode {
+	case ECB_MODE:
+		ret = NewECBDecrypter(block)
+		sc.needPadding = true
+	case CBC_MODE:
+		ret = cipher.NewCBCDecrypter(block, iv)
+		sc.needPadding = true
+	case CFB_MODE:
+		ret = cipher.NewCFBDecrypter(block, iv)
+		sc.needPadding = false
+	case OFB_MODE:
+		ret = cipher.NewOFB(block, iv)
+		sc.needPadding = false
+	default:
+		err = errors.New("invalidCipherMode")
+	}
+	return
+}
+
+// 补码
+func pkcs77Padding(ciphertext []byte, blocksize int) []byte {
+	padding := blocksize - len(ciphertext)%blocksize
+	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
+	return append(ciphertext, padtext...)
+}
+
+// 去码
+func pkcs7UnPadding(origData []byte) []byte {
+	length := len(origData)
+	unpadding := int(origData[length-1])
+	return origData[:length-unpadding]
+}
+
+// 补码
+func pkcs5Padding(ciphertext []byte) []byte {
+	return pkcs77Padding(ciphertext, 8)
+}
+
+// 去码
+func pkcs5UnPadding(ciphertext []byte) []byte {
+	return pkcs7UnPadding(ciphertext)
+}

+ 142 - 0
security/zzf.go

@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package security
+
+import (
+	"crypto/md5"
+	"errors"
+	"fmt"
+	"reflect"
+	"unsafe"
+)
+
+type ThirdPartCipher struct {
+	encryptType int    // 外部加密算法id
+	encryptName string // 外部加密算法名称
+	hashType    int
+	key         []byte
+	cipherCount int // 外部加密算法个数
+	//innerId		int // 外部加密算法内部id
+	blockSize int // 分组块大小
+	khSize    int // key/hash大小
+}
+
+func NewThirdPartCipher(encryptType int, key []byte, cipherPath string, hashType int) (ThirdPartCipher, error) {
+	var tpc = ThirdPartCipher{
+		encryptType: encryptType,
+		key:         key,
+		hashType:    hashType,
+		cipherCount: -1,
+	}
+	var err error
+	err = initThirdPartCipher(cipherPath)
+	if err != nil {
+		return tpc, err
+	}
+	tpc.getCount()
+	if err = tpc.getInfo(); err != nil {
+		return tpc, err
+	}
+	return tpc, nil
+}
+
+func (tpc *ThirdPartCipher) getCount() int {
+	if tpc.cipherCount == -1 {
+		tpc.cipherCount = cipherGetCount()
+	}
+	return tpc.cipherCount
+}
+
+func (tpc *ThirdPartCipher) getInfo() error {
+	var cipher_id, ty, blk_size, kh_size int
+	//var strptr, _ = syscall.UTF16PtrFromString(tpc.encryptName)
+	var strptr *uint16 = new(uint16)
+	for i := 1; i <= tpc.getCount(); i++ {
+		cipherGetInfo(uintptr(i), uintptr(unsafe.Pointer(&cipher_id)), uintptr(unsafe.Pointer(&strptr)),
+			uintptr(unsafe.Pointer(&ty)), uintptr(unsafe.Pointer(&blk_size)), uintptr(unsafe.Pointer(&kh_size)))
+		if tpc.encryptType == cipher_id {
+			tpc.blockSize = blk_size
+			tpc.khSize = kh_size
+			tpc.encryptName = string(uintptr2bytes(uintptr(unsafe.Pointer(strptr))))
+			return nil
+		}
+	}
+	return fmt.Errorf("ThirdPartyCipher: cipher id:%d not found", tpc.encryptType)
+}
+
+func (tpc ThirdPartCipher) Encrypt(plaintext []byte, genDigest bool) []byte {
+	var tmp_para uintptr
+	cipherEncryptInit(uintptr(tpc.encryptType), uintptr(unsafe.Pointer(&tpc.key[0])), uintptr(len(tpc.key)), tmp_para)
+
+	ciphertextLen := cipherGetCipherTextSize(uintptr(tpc.encryptType), tmp_para, uintptr(len(plaintext)))
+
+	ciphertext := make([]byte, ciphertextLen)
+	ret := cipherEncrypt(uintptr(tpc.encryptType), tmp_para, uintptr(unsafe.Pointer(&plaintext[0])), uintptr(len(plaintext)),
+		uintptr(unsafe.Pointer(&ciphertext[0])), uintptr(len(ciphertext)))
+	ciphertext = ciphertext[:ret]
+
+	cipherClean(uintptr(tpc.encryptType), tmp_para)
+	// md5摘要
+	if genDigest {
+		digest := md5.Sum(plaintext)
+		encrypt := ciphertext
+		ciphertext = make([]byte, len(encrypt)+len(digest))
+		copy(ciphertext[:len(encrypt)], encrypt)
+		copy(ciphertext[len(encrypt):], digest[:])
+	}
+	return ciphertext
+}
+
+func (tpc ThirdPartCipher) Decrypt(ciphertext []byte, checkDigest bool) ([]byte, error) {
+	var ret []byte
+	if checkDigest {
+		var digest = ciphertext[len(ciphertext)-MD5_DIGEST_SIZE:]
+		ret = ciphertext[:len(ciphertext)-MD5_DIGEST_SIZE]
+		ret = tpc.decrypt(ret)
+		var msgDigest = md5.Sum(ret)
+		if !reflect.DeepEqual(msgDigest[:], digest) {
+			return nil, errors.New("Decrypt failed/Digest not match\n")
+		}
+	} else {
+		ret = tpc.decrypt(ciphertext)
+	}
+	return ret, nil
+}
+
+func (tpc ThirdPartCipher) decrypt(ciphertext []byte) []byte {
+	var tmp_para uintptr
+
+	cipherDecryptInit(uintptr(tpc.encryptType), uintptr(unsafe.Pointer(&tpc.key[0])), uintptr(len(tpc.key)), tmp_para)
+
+	plaintext := make([]byte, len(ciphertext))
+	ret := cipherDecrypt(uintptr(tpc.encryptType), tmp_para, uintptr(unsafe.Pointer(&ciphertext[0])), uintptr(len(ciphertext)),
+		uintptr(unsafe.Pointer(&plaintext[0])), uintptr(len(plaintext)))
+	plaintext = plaintext[:ret]
+
+	cipherClean(uintptr(tpc.encryptType), tmp_para)
+	return plaintext
+}
+
+func addBufSize(buf []byte, newCap int) []byte {
+	newBuf := make([]byte, newCap)
+	copy(newBuf, buf)
+	return newBuf
+}
+
+func uintptr2bytes(p uintptr) []byte {
+	buf := make([]byte, 64)
+	i := 0
+	for b := (*byte)(unsafe.Pointer(p)); *b != 0; i++ {
+		if i > cap(buf) {
+			buf = addBufSize(buf, i*2)
+		}
+		buf[i] = *b
+		// byte占1字节
+		p++
+		b = (*byte)(unsafe.Pointer(p))
+	}
+	return buf[:i]
+}

+ 96 - 0
security/zzg_darwin.go

@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package security
+
+import "plugin"
+
+var (
+	dmCipherEncryptSo           *plugin.Plugin
+	cipherGetCountProc          plugin.Symbol
+	cipherGetInfoProc           plugin.Symbol
+	cipherEncryptInitProc       plugin.Symbol
+	cipherGetCipherTextSizeProc plugin.Symbol
+	cipherEncryptProc           plugin.Symbol
+	cipherCleanupProc           plugin.Symbol
+	cipherDecryptInitProc       plugin.Symbol
+	cipherDecryptProc           plugin.Symbol
+)
+
+func initThirdPartCipher(cipherPath string) (err error) {
+	if dmCipherEncryptSo, err = plugin.Open(cipherPath); err != nil {
+		return err
+	}
+	if cipherGetCountProc, err = dmCipherEncryptSo.Lookup("cipher_get_count"); err != nil {
+		return err
+	}
+	if cipherGetInfoProc, err = dmCipherEncryptSo.Lookup("cipher_get_info"); err != nil {
+		return err
+	}
+	if cipherEncryptInitProc, err = dmCipherEncryptSo.Lookup("cipher_encrypt_init"); err != nil {
+		return err
+	}
+	if cipherGetCipherTextSizeProc, err = dmCipherEncryptSo.Lookup("cipher_get_cipher_text_size"); err != nil {
+		return err
+	}
+	if cipherEncryptProc, err = dmCipherEncryptSo.Lookup("cipher_encrypt"); err != nil {
+		return err
+	}
+	if cipherCleanupProc, err = dmCipherEncryptSo.Lookup("cipher_cleanup"); err != nil {
+		return err
+	}
+	if cipherDecryptInitProc, err = dmCipherEncryptSo.Lookup("cipher_decrypt_init"); err != nil {
+		return err
+	}
+	if cipherDecryptProc, err = dmCipherEncryptSo.Lookup("cipher_decrypt"); err != nil {
+		return err
+	}
+	return nil
+}
+
+func cipherGetCount() int {
+	ret := cipherGetCountProc.(func() interface{})()
+	return ret.(int)
+}
+
+func cipherGetInfo(seqno, cipherId, cipherName, _type, blkSize, khSIze uintptr) {
+	ret := cipherGetInfoProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(seqno, cipherId, cipherName, _type, blkSize, khSIze)
+	if ret.(int) == 0 {
+		panic("ThirdPartyCipher: call cipher_get_info failed")
+	}
+}
+
+func cipherEncryptInit(cipherId, key, keySize, cipherPara uintptr) {
+	ret := cipherEncryptInitProc.(func(uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, key, keySize, cipherPara)
+	if ret.(int) == 0 {
+		panic("ThirdPartyCipher: call cipher_encrypt_init failed")
+	}
+}
+
+func cipherGetCipherTextSize(cipherId, cipherPara, plainTextSize uintptr) uintptr {
+	ciphertextLen := cipherGetCipherTextSizeProc.(func(uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, plainTextSize)
+	return ciphertextLen.(uintptr)
+}
+
+func cipherEncrypt(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize uintptr) uintptr {
+	ret := cipherEncryptProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize)
+	return ret.(uintptr)
+}
+
+func cipherClean(cipherId, cipherPara uintptr) {
+	cipherEncryptProc.(func(uintptr, uintptr))(cipherId, cipherPara)
+}
+
+func cipherDecryptInit(cipherId, key, keySize, cipherPara uintptr) {
+	ret := cipherDecryptInitProc.(func(uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, key, keySize, cipherPara)
+	if ret.(int) == 0 {
+		panic("ThirdPartyCipher: call cipher_decrypt_init failed")
+	}
+}
+
+func cipherDecrypt(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize uintptr) uintptr {
+	ret := cipherDecryptProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize)
+	return ret.(uintptr)
+}

+ 96 - 0
security/zzg_linux.go

@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package security
+
+import "plugin"
+
+var (
+	dmCipherEncryptSo           *plugin.Plugin
+	cipherGetCountProc          plugin.Symbol
+	cipherGetInfoProc           plugin.Symbol
+	cipherEncryptInitProc       plugin.Symbol
+	cipherGetCipherTextSizeProc plugin.Symbol
+	cipherEncryptProc           plugin.Symbol
+	cipherCleanupProc           plugin.Symbol
+	cipherDecryptInitProc       plugin.Symbol
+	cipherDecryptProc           plugin.Symbol
+)
+
+func initThirdPartCipher(cipherPath string) (err error) {
+	if dmCipherEncryptSo, err = plugin.Open(cipherPath); err != nil {
+		return err
+	}
+	if cipherGetCountProc, err = dmCipherEncryptSo.Lookup("cipher_get_count"); err != nil {
+		return err
+	}
+	if cipherGetInfoProc, err = dmCipherEncryptSo.Lookup("cipher_get_info"); err != nil {
+		return err
+	}
+	if cipherEncryptInitProc, err = dmCipherEncryptSo.Lookup("cipher_encrypt_init"); err != nil {
+		return err
+	}
+	if cipherGetCipherTextSizeProc, err = dmCipherEncryptSo.Lookup("cipher_get_cipher_text_size"); err != nil {
+		return err
+	}
+	if cipherEncryptProc, err = dmCipherEncryptSo.Lookup("cipher_encrypt"); err != nil {
+		return err
+	}
+	if cipherCleanupProc, err = dmCipherEncryptSo.Lookup("cipher_cleanup"); err != nil {
+		return err
+	}
+	if cipherDecryptInitProc, err = dmCipherEncryptSo.Lookup("cipher_decrypt_init"); err != nil {
+		return err
+	}
+	if cipherDecryptProc, err = dmCipherEncryptSo.Lookup("cipher_decrypt"); err != nil {
+		return err
+	}
+	return nil
+}
+
+func cipherGetCount() int {
+	ret := cipherGetCountProc.(func() interface{})()
+	return ret.(int)
+}
+
+func cipherGetInfo(seqno, cipherId, cipherName, _type, blkSize, khSIze uintptr) {
+	ret := cipherGetInfoProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(seqno, cipherId, cipherName, _type, blkSize, khSIze)
+	if ret.(int) == 0 {
+		panic("ThirdPartyCipher: call cipher_get_info failed")
+	}
+}
+
+func cipherEncryptInit(cipherId, key, keySize, cipherPara uintptr) {
+	ret := cipherEncryptInitProc.(func(uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, key, keySize, cipherPara)
+	if ret.(int) == 0 {
+		panic("ThirdPartyCipher: call cipher_encrypt_init failed")
+	}
+}
+
+func cipherGetCipherTextSize(cipherId, cipherPara, plainTextSize uintptr) uintptr {
+	ciphertextLen := cipherGetCipherTextSizeProc.(func(uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, plainTextSize)
+	return ciphertextLen.(uintptr)
+}
+
+func cipherEncrypt(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize uintptr) uintptr {
+	ret := cipherEncryptProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize)
+	return ret.(uintptr)
+}
+
+func cipherClean(cipherId, cipherPara uintptr) {
+	cipherEncryptProc.(func(uintptr, uintptr))(cipherId, cipherPara)
+}
+
+func cipherDecryptInit(cipherId, key, keySize, cipherPara uintptr) {
+	ret := cipherDecryptInitProc.(func(uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, key, keySize, cipherPara)
+	if ret.(int) == 0 {
+		panic("ThirdPartyCipher: call cipher_decrypt_init failed")
+	}
+}
+
+func cipherDecrypt(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize uintptr) uintptr {
+	ret := cipherDecryptProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize)
+	return ret.(uintptr)
+}

+ 83 - 0
security/zzh_windows.go

@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package security
+
+import (
+	"syscall"
+)
+
+var (
+	dmCipherEncryptDLL          *syscall.LazyDLL
+	cipherGetCountProc          *syscall.LazyProc
+	cipherGetInfoProc           *syscall.LazyProc
+	cipherEncryptInitProc       *syscall.LazyProc
+	cipherGetCipherTextSizeProc *syscall.LazyProc
+	cipherEncryptProc           *syscall.LazyProc
+	cipherCleanupProc           *syscall.LazyProc
+	cipherDecryptInitProc       *syscall.LazyProc
+	cipherDecryptProc           *syscall.LazyProc
+)
+
+func initThirdPartCipher(cipherPath string) error {
+	dmCipherEncryptDLL = syscall.NewLazyDLL(cipherPath)
+	if err := dmCipherEncryptDLL.Load(); err != nil {
+		return err
+	}
+	cipherGetCountProc = dmCipherEncryptDLL.NewProc("cipher_get_count")
+	cipherGetInfoProc = dmCipherEncryptDLL.NewProc("cipher_get_info")
+	cipherEncryptInitProc = dmCipherEncryptDLL.NewProc("cipher_encrypt_init")
+	cipherGetCipherTextSizeProc = dmCipherEncryptDLL.NewProc("cipher_get_cipher_text_size")
+	cipherEncryptProc = dmCipherEncryptDLL.NewProc("cipher_encrypt")
+	cipherCleanupProc = dmCipherEncryptDLL.NewProc("cipher_cleanup")
+	cipherDecryptInitProc = dmCipherEncryptDLL.NewProc("cipher_decrypt_init")
+	cipherDecryptProc = dmCipherEncryptDLL.NewProc("cipher_decrypt")
+	return nil
+}
+
+func cipherGetCount() int {
+	ret, _, _ := cipherGetCountProc.Call()
+	return int(ret)
+}
+
+func cipherGetInfo(seqno, cipherId, cipherName, _type, blkSize, khSIze uintptr) {
+	ret, _, _ := cipherGetInfoProc.Call(seqno, cipherId, cipherName, _type, blkSize, khSIze)
+	if ret == 0 {
+		panic("ThirdPartyCipher: call cipher_get_info failed")
+	}
+}
+
+func cipherEncryptInit(cipherId, key, keySize, cipherPara uintptr) {
+	ret, _, _ := cipherEncryptInitProc.Call(cipherId, key, keySize, cipherPara)
+	if ret == 0 {
+		panic("ThirdPartyCipher: call cipher_encrypt_init failed")
+	}
+}
+
+func cipherGetCipherTextSize(cipherId, cipherPara, plainTextSize uintptr) uintptr {
+	ciphertextLen, _, _ := cipherGetCipherTextSizeProc.Call(cipherId, cipherPara, plainTextSize)
+	return ciphertextLen
+}
+
+func cipherEncrypt(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize uintptr) uintptr {
+	ret, _, _ := cipherEncryptProc.Call(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize)
+	return ret
+}
+
+func cipherClean(cipherId, cipherPara uintptr) {
+	_, _, _ = cipherCleanupProc.Call(cipherId, cipherPara)
+}
+
+func cipherDecryptInit(cipherId, key, keySize, cipherPara uintptr) {
+	ret, _, _ := cipherDecryptInitProc.Call(cipherId, key, keySize, cipherPara)
+	if ret == 0 {
+		panic("ThirdPartyCipher: call cipher_decrypt_init failed")
+	}
+}
+
+func cipherDecrypt(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize uintptr) uintptr {
+	ret, _, _ := cipherDecryptProc.Call(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize)
+	return ret
+}

+ 50 - 0
security/zzi.go

@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package security
+
+import (
+	"crypto/tls"
+	"errors"
+	"flag"
+	"net"
+	"os"
+	"sync"
+)
+
+var dmHome = flag.String("DM_HOME", "", "Where DMDB installed")
+var lock = sync.Mutex{}
+
+func NewTLSFromTCP(conn *net.TCPConn, sslCertPath string, sslKeyPath string, user string) (*tls.Conn, error) {
+	if sslCertPath == "" && sslKeyPath == "" {
+		func() {
+			lock.Lock()
+			defer lock.Unlock()
+			flag.Parse()
+		}()
+		separator := string(os.PathSeparator)
+		if *dmHome != "" {
+			sslCertPath = *dmHome + separator + "bin" + separator + "client_ssl" + separator +
+				user + separator + "client-cert.pem"
+			sslKeyPath = *dmHome + separator + "bin" + separator + "client_ssl" + separator +
+				user + separator + "client-key.pem"
+		} else {
+			return nil, errors.New("sslCertPath and sslKeyPath can not be empty!")
+		}
+	}
+	cer, err := tls.LoadX509KeyPair(sslCertPath, sslKeyPath)
+	if err != nil {
+		return nil, err
+	}
+	conf := &tls.Config{
+		InsecureSkipVerify: true,
+		Certificates:       []tls.Certificate{cer},
+	}
+	tlsConn := tls.Client(conn, conf)
+	if err := tlsConn.Handshake(); err != nil {
+		return nil, err
+	}
+	return tlsConn, nil
+}

+ 522 - 0
t.go

@@ -0,0 +1,522 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"database/sql/driver"
+	"io"
+	"reflect"
+	"strings"
+)
+
+type DmRows struct {
+	filterable
+	CurrentRows *innerRows
+	finish      func()
+}
+
+func (r *DmRows) Columns() []string {
+	if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
+		return nil
+	}
+	if len(r.filterChain.filters) == 0 {
+		return r.columns()
+	}
+	return r.filterChain.reset().DmRowsColumns(r)
+}
+
+func (r *DmRows) Close() error {
+	if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
+		return err
+	}
+	if len(r.filterChain.filters) == 0 {
+		return r.close()
+	}
+	return r.filterChain.reset().DmRowsClose(r)
+}
+
+func (r *DmRows) Next(dest []driver.Value) error {
+	if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
+		return err
+	}
+	if len(r.filterChain.filters) == 0 {
+		return r.next(dest)
+	}
+	return r.filterChain.reset().DmRowsNext(r, dest)
+}
+
+func (r *DmRows) HasNextResultSet() bool {
+	if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
+		return false
+	}
+	if len(r.filterChain.filters) == 0 {
+		return r.hasNextResultSet()
+	}
+	return r.filterChain.reset().DmRowsHasNextResultSet(r)
+}
+
+func (r *DmRows) NextResultSet() error {
+	if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
+		return err
+	}
+	if len(r.filterChain.filters) == 0 {
+		return r.nextResultSet()
+	}
+	return r.filterChain.reset().DmRowsNextResultSet(r)
+}
+
+func (r *DmRows) ColumnTypeScanType(index int) reflect.Type {
+	if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
+		return nil
+	}
+	if len(r.filterChain.filters) == 0 {
+		return r.columnTypeScanType(index)
+	}
+	return r.filterChain.reset().DmRowsColumnTypeScanType(r, index)
+}
+
+func (r *DmRows) ColumnTypeDatabaseTypeName(index int) string {
+	if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
+		return ""
+	}
+	if len(r.filterChain.filters) == 0 {
+		return r.columnTypeDatabaseTypeName(index)
+	}
+	return r.filterChain.reset().DmRowsColumnTypeDatabaseTypeName(r, index)
+}
+
+func (r *DmRows) ColumnTypeLength(index int) (length int64, ok bool) {
+	if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
+		return -1, false
+	}
+	if len(r.filterChain.filters) == 0 {
+		return r.columnTypeLength(index)
+	}
+	return r.filterChain.reset().DmRowsColumnTypeLength(r, index)
+}
+
+func (r *DmRows) ColumnTypeNullable(index int) (nullable, ok bool) {
+	if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
+		return false, false
+	}
+	if len(r.filterChain.filters) == 0 {
+		return r.columnTypeNullable(index)
+	}
+	return r.filterChain.reset().DmRowsColumnTypeNullable(r, index)
+}
+
+func (r *DmRows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) {
+	if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
+		return -1, -1, false
+	}
+	if len(r.filterChain.filters) == 0 {
+		return r.columnTypePrecisionScale(index)
+	}
+	return r.filterChain.reset().DmRowsColumnTypePrecisionScale(r, index)
+}
+
+func (dest *DmRows) Scan(src interface{}) error {
+	switch src := src.(type) {
+	case nil:
+		*dest = *new(DmRows)
+		return nil
+	case *DmRows:
+		*dest = *src
+		return nil
+	default:
+		return UNSUPPORTED_SCAN
+	}
+}
+
+func (rows *DmRows) columns() []string {
+	return rows.CurrentRows.Columns()
+}
+
+func (rows *DmRows) close() error {
+	if f := rows.finish; f != nil {
+		f()
+		rows.finish = nil
+	}
+	return rows.CurrentRows.Close()
+}
+
+func (rows *DmRows) next(dest []driver.Value) error {
+	return rows.CurrentRows.Next(dest)
+}
+
+func (rows *DmRows) hasNextResultSet() bool {
+	return rows.CurrentRows.HasNextResultSet()
+}
+
+func (rows *DmRows) nextResultSet() error {
+	return rows.CurrentRows.NextResultSet()
+}
+
+func (rows *DmRows) columnTypeScanType(index int) reflect.Type {
+	return rows.CurrentRows.ColumnTypeScanType(index)
+}
+
+func (rows *DmRows) columnTypeDatabaseTypeName(index int) string {
+	return rows.CurrentRows.ColumnTypeDatabaseTypeName(index)
+}
+
+func (rows *DmRows) columnTypeLength(index int) (length int64, ok bool) {
+	return rows.CurrentRows.ColumnTypeLength(index)
+}
+
+func (rows *DmRows) columnTypeNullable(index int) (nullable, ok bool) {
+	return rows.CurrentRows.ColumnTypeNullable(index)
+}
+
+func (rows *DmRows) columnTypePrecisionScale(index int) (precision, scale int64, ok bool) {
+	return rows.CurrentRows.ColumnTypePrecisionScale(index)
+}
+
+type innerRows struct {
+	dmStmt *DmStatement
+
+	id int16
+
+	columns []column
+
+	datas [][][]byte
+
+	datasOffset int
+
+	datasStartPos int64
+
+	currentPos int64
+
+	totalRowCount int64
+
+	fetchSize int
+
+	sizeOfRow int
+
+	isBdta bool
+
+	nextExecInfo *execRetInfo
+
+	next *innerRows
+
+	dmRows *DmRows
+
+	closed bool
+}
+
+func (innerRows *innerRows) checkClosed() error {
+	if innerRows.closed {
+		return ECGO_RESULTSET_CLOSED.throw()
+	}
+	return nil
+}
+
+func (innerRows *innerRows) Columns() []string {
+	if err := innerRows.checkClosed(); err != nil {
+		return nil
+	}
+
+	columnNames := make([]string, len(innerRows.columns))
+	nameCase := innerRows.dmStmt.dmConn.dmConnector.columnNameCase
+
+	for i, column := range innerRows.columns {
+		if nameCase == COLUMN_NAME_NATURAL_CASE {
+			columnNames[i] = column.name
+		} else if nameCase == COLUMN_NAME_UPPER_CASE {
+			columnNames[i] = strings.ToUpper(column.name)
+		} else if nameCase == COLUMN_NAME_LOWER_CASE {
+			columnNames[i] = strings.ToLower(column.name)
+		} else {
+			columnNames[i] = column.name
+		}
+	}
+
+	return columnNames
+}
+
+func (innerRows *innerRows) Close() error {
+	if innerRows.closed {
+		return nil
+	}
+
+	innerRows.closed = true
+
+	if innerRows.dmStmt.innerUsed {
+		innerRows.dmStmt.close()
+	} else {
+		delete(innerRows.dmStmt.rsMap, innerRows.id)
+	}
+
+	innerRows.dmStmt = nil
+
+	return nil
+}
+
+func (innerRows *innerRows) Next(dest []driver.Value) error {
+	err := innerRows.checkClosed()
+	if err != nil {
+		return err
+	}
+
+	if innerRows.totalRowCount == 0 || innerRows.currentPos >= innerRows.totalRowCount {
+		return io.EOF
+	}
+
+	if innerRows.currentPos+1 == innerRows.totalRowCount {
+		innerRows.currentPos++
+		innerRows.datasOffset++
+		return io.EOF
+	}
+
+	if innerRows.currentPos+1 < innerRows.datasStartPos || innerRows.currentPos+1 >= innerRows.datasStartPos+int64(len(innerRows.datas)) {
+		if innerRows.fetchData(innerRows.currentPos + 1) {
+			innerRows.currentPos++
+			err := innerRows.getRowData(dest)
+			if err != nil {
+				return err
+			}
+		} else {
+			innerRows.currentPos++
+			innerRows.datasOffset++
+			return io.EOF
+		}
+	} else {
+		innerRows.currentPos++
+		innerRows.datasOffset++
+		err := innerRows.getRowData(dest)
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
+func (innerRows *innerRows) HasNextResultSet() bool {
+	err := innerRows.checkClosed()
+	if err != nil {
+		return false
+	}
+
+	if innerRows.nextExecInfo != nil {
+		return innerRows.nextExecInfo.hasResultSet
+	}
+
+	innerRows.nextExecInfo, err = innerRows.dmStmt.dmConn.Access.Dm_build_814(innerRows.dmStmt, 0)
+	if err != nil {
+		return false
+	}
+
+	if innerRows.nextExecInfo.hasResultSet {
+		innerRows.next = newInnerRows(innerRows.id+1, innerRows.dmStmt, innerRows.nextExecInfo)
+		return true
+	}
+
+	return false
+}
+
+func (innerRows *innerRows) NextResultSet() error {
+	err := innerRows.checkClosed()
+	if err != nil {
+		return err
+	}
+
+	if innerRows.nextExecInfo == nil {
+		innerRows.HasNextResultSet()
+	}
+
+	if innerRows.next == nil {
+		return io.EOF
+	}
+
+	innerRows.next.dmRows = innerRows.dmRows
+	innerRows.dmRows.CurrentRows = innerRows.next
+	return nil
+}
+
+func (innerRows *innerRows) ColumnTypeScanType(index int) reflect.Type {
+	if err := innerRows.checkClosed(); err != nil {
+		return nil
+	}
+	if column := innerRows.checkIndex(index); column != nil {
+		return column.ScanType()
+	}
+	return nil
+}
+
+func (innerRows *innerRows) ColumnTypeDatabaseTypeName(index int) string {
+	if err := innerRows.checkClosed(); err != nil {
+		return ""
+	}
+	if column := innerRows.checkIndex(index); column != nil {
+		return column.typeName
+	}
+	return ""
+}
+
+func (innerRows *innerRows) ColumnTypeLength(index int) (length int64, ok bool) {
+	if err := innerRows.checkClosed(); err != nil {
+		return 0, false
+	}
+	if column := innerRows.checkIndex(index); column != nil {
+		return column.Length()
+	}
+	return 0, false
+}
+
+func (innerRows *innerRows) ColumnTypeNullable(index int) (nullable, ok bool) {
+	if err := innerRows.checkClosed(); err != nil {
+		return false, false
+	}
+	if column := innerRows.checkIndex(index); column != nil {
+		return column.nullable, true
+	}
+	return false, false
+}
+
+func (innerRows *innerRows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) {
+	if err := innerRows.checkClosed(); err != nil {
+		return 0, 0, false
+	}
+	if column := innerRows.checkIndex(index); column != nil {
+		return column.PrecisionScale()
+	}
+	return 0, 0, false
+}
+
+func newDmRows(currentRows *innerRows) *DmRows {
+	dr := new(DmRows)
+	dr.resetFilterable(&currentRows.dmStmt.filterable)
+	dr.CurrentRows = currentRows
+	dr.idGenerator = dmRowsIDGenerator
+	currentRows.dmRows = dr
+	return dr
+}
+
+func newInnerRows(id int16, stmt *DmStatement, execInfo *execRetInfo) *innerRows {
+	rows := new(innerRows)
+	rows.id = id
+	rows.dmStmt = stmt
+	rows.columns = stmt.columns
+	rows.datas = execInfo.rsDatas
+	rows.totalRowCount = execInfo.updateCount
+	rows.isBdta = execInfo.rsBdta
+	rows.fetchSize = stmt.fetchSize
+
+	if len(execInfo.rsDatas) == 0 {
+		rows.sizeOfRow = 0
+	} else {
+		rows.sizeOfRow = execInfo.rsSizeof / len(execInfo.rsDatas)
+	}
+
+	rows.currentPos = -1
+	rows.datasOffset = -1
+	rows.datasStartPos = 0
+
+	rows.nextExecInfo = nil
+	rows.next = nil
+
+	if rows.dmStmt.rsMap != nil {
+		rows.dmStmt.rsMap[rows.id] = rows
+	}
+
+	if stmt.dmConn.dmConnector.enRsCache && execInfo.rsCacheOffset > 0 &&
+		int64(len(execInfo.rsDatas)) == execInfo.updateCount {
+		rp.put(stmt, stmt.nativeSql, execInfo)
+	}
+
+	return rows
+}
+
+func newLocalInnerRows(stmt *DmStatement, columns []column, rsDatas [][][]byte) *innerRows {
+	rows := new(innerRows)
+	rows.id = 0
+	rows.dmStmt = stmt
+	rows.fetchSize = stmt.fetchSize
+
+	if columns == nil {
+		rows.columns = make([]column, 0)
+	} else {
+		rows.columns = columns
+	}
+
+	if rsDatas == nil {
+		rows.datas = make([][][]byte, 0)
+		rows.totalRowCount = 0
+	} else {
+		rows.datas = rsDatas
+		rows.totalRowCount = int64(len(rsDatas))
+	}
+
+	rows.isBdta = false
+	return rows
+}
+
+func (innerRows *innerRows) checkIndex(index int) *column {
+	if index < 0 || index > len(innerRows.columns)-1 {
+		return nil
+	}
+
+	return &innerRows.columns[index]
+}
+
+func (innerRows *innerRows) fetchData(startPos int64) bool {
+	execInfo, err := innerRows.dmStmt.dmConn.Access.Dm_build_821(innerRows, startPos)
+	if err != nil {
+		return false
+	}
+
+	innerRows.totalRowCount = execInfo.updateCount
+	if execInfo.rsDatas != nil {
+		innerRows.datas = execInfo.rsDatas
+		innerRows.datasStartPos = startPos
+		innerRows.datasOffset = 0
+		return true
+	}
+
+	return false
+}
+
+func (innerRows *innerRows) getRowData(dest []driver.Value) (err error) {
+	for i, column := range innerRows.columns {
+
+		if i <= len(dest)-1 {
+			if column.colType == CURSOR {
+				var tmpExecInfo *execRetInfo
+				tmpExecInfo, err = innerRows.dmStmt.dmConn.Access.Dm_build_814(innerRows.dmStmt, 1)
+				if err != nil {
+					return err
+				}
+
+				if tmpExecInfo.hasResultSet {
+					dest[i] = newDmRows(newInnerRows(innerRows.id+1, innerRows.dmStmt, tmpExecInfo))
+				} else {
+					dest[i] = nil
+				}
+				continue
+			}
+
+			dest[i], err = column.getColumnData(innerRows.datas[innerRows.datasOffset][i+1], innerRows.dmStmt.dmConn)
+			innerRows.columns[i].isBdta = innerRows.isBdta
+			if err != nil {
+				return err
+			}
+		} else {
+			return nil
+		}
+	}
+
+	return nil
+}
+
+func (innerRows *innerRows) getRowCount() int64 {
+	innerRows.checkClosed()
+
+	if innerRows.totalRowCount == INT64_MAX {
+		return -1
+	}
+
+	return innerRows.totalRowCount
+}

+ 1514 - 0
u.go

@@ -0,0 +1,1514 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"container/list"
+	"context"
+	"database/sql"
+	"database/sql/driver"
+	"fmt"
+	"io"
+	"math/big"
+	"reflect"
+	"strconv"
+	"strings"
+	"time"
+
+	"gitee.com/chunanyong/dm/util"
+)
+
+var rp = newRsPool()
+
+type DmStatement struct {
+	filterable
+
+	dmConn    *DmConnection
+	rsMap     map[int16]*innerRows
+	inUse     bool
+	innerUsed bool
+
+	innerExec bool
+
+	id int32
+
+	cursorName string
+
+	readBaseColName bool
+
+	execInfo *execRetInfo
+
+	resultSetType int
+
+	resultSetConcurrency int
+
+	resultSetHoldability int
+
+	nativeSql string
+
+	maxFieldSize int
+
+	maxRows int64
+
+	escapeProcessing bool
+
+	queryTimeout int32
+
+	fetchDirection int
+
+	fetchSize int
+
+	cursorUpdateRow int64
+
+	closeOnCompletion bool
+
+	isBatch bool
+
+	closed bool
+
+	columns []column
+
+	serverParams []parameter
+
+	bindParams []parameter
+
+	paramCount int32
+
+	preExec bool
+}
+
+type stmtPoolInfo struct {
+	id int32
+
+	cursorName string
+
+	readBaseColName bool
+}
+
+type rsPoolKey struct {
+	dbGuid        string
+	currentSchema string
+	sql           string
+	paramCount    int
+}
+
+func newRsPoolKey(stmt *DmStatement, sql string) rsPoolKey {
+	rpk := new(rsPoolKey)
+	rpk.dbGuid = stmt.dmConn.Guid
+	rpk.currentSchema = stmt.dmConn.Schema
+	rpk.paramCount = int(stmt.paramCount)
+
+	rpk.sql = sql
+	return *rpk
+}
+
+func (key rsPoolKey) equals(destKey rsPoolKey) bool {
+	return key.dbGuid == destKey.dbGuid &&
+		key.currentSchema == destKey.currentSchema &&
+		key.sql == destKey.sql &&
+		key.paramCount == destKey.paramCount
+
+}
+
+type rsPoolValue struct {
+	m_lastChkTime int
+	m_TbIds       []int32
+	m_TbTss       []int64
+	execInfo      *execRetInfo
+}
+
+func newRsPoolValue(execInfo *execRetInfo) rsPoolValue {
+	rpv := new(rsPoolValue)
+	rpv.execInfo = execInfo
+	rpv.m_lastChkTime = time.Now().Nanosecond()
+	copy(rpv.m_TbIds, execInfo.tbIds)
+	copy(rpv.m_TbTss, execInfo.tbTss)
+	return *rpv
+}
+
+func (rpv rsPoolValue) refreshed(conn *DmConnection) (bool, error) {
+
+	if conn.dmConnector.rsRefreshFreq == 0 {
+		return false, nil
+	}
+
+	if rpv.m_lastChkTime+conn.dmConnector.rsRefreshFreq*int(time.Second) > time.Now().Nanosecond() {
+		return false, nil
+	}
+
+	tss, err := conn.Access.Dm_build_847(interface{}(rpv.m_TbIds).([]uint32))
+	if err != nil {
+		return false, err
+	}
+	rpv.m_lastChkTime = time.Now().Nanosecond()
+
+	var tbCount int
+	if tss != nil {
+		tbCount = len(tss)
+	}
+
+	if tbCount != len(rpv.m_TbTss) {
+		return true, nil
+	}
+
+	for i := 0; i < tbCount; i++ {
+		if rpv.m_TbTss[i] != tss[i] {
+			return true, nil
+		}
+
+	}
+	return false, nil
+}
+
+func (rpv rsPoolValue) getResultSet(stmt *DmStatement) *innerRows {
+	destDatas := rpv.execInfo.rsDatas
+	var totalRows int
+	if rpv.execInfo.rsDatas != nil {
+		totalRows = len(rpv.execInfo.rsDatas)
+	}
+
+	if stmt.maxRows > 0 && stmt.maxRows < int64(totalRows) {
+		destDatas = make([][][]byte, stmt.maxRows)
+		copy(destDatas[:len(destDatas)], rpv.execInfo.rsDatas[:len(destDatas)])
+	}
+
+	rs := newLocalInnerRows(stmt, stmt.columns, destDatas)
+	rs.id = 1
+	return rs
+}
+
+func (rpv rsPoolValue) getDataLen() int {
+	return rpv.execInfo.rsSizeof
+}
+
+type rsPool struct {
+	rsMap        map[rsPoolKey]rsPoolValue
+	rsList       *list.List
+	totalDataLen int
+}
+
+func newRsPool() *rsPool {
+	rp := new(rsPool)
+	rp.rsMap = make(map[rsPoolKey]rsPoolValue, 100)
+	rp.rsList = list.New()
+	return rp
+}
+
+func (rp *rsPool) removeInList(key rsPoolKey) {
+	for e := rp.rsList.Front(); e != nil && e.Value.(rsPoolKey).equals(key); e = e.Next() {
+		rp.rsList.Remove(e)
+	}
+}
+
+func (rp *rsPool) put(stmt *DmStatement, sql string, execInfo *execRetInfo) {
+	var dataLen int
+	if execInfo != nil {
+		dataLen = execInfo.rsSizeof
+	}
+
+	cacheSize := stmt.dmConn.dmConnector.rsCacheSize * 1024 * 1024
+
+	for rp.totalDataLen+dataLen > cacheSize {
+		if rp.totalDataLen == 0 {
+			return
+		}
+
+		lk := rp.rsList.Back().Value.(rsPoolKey)
+		rp.totalDataLen -= rp.rsMap[lk].getDataLen()
+		rp.rsList.Remove(rp.rsList.Back())
+		delete(rp.rsMap, rp.rsList.Back().Value.(rsPoolKey))
+	}
+
+	key := newRsPoolKey(stmt, sql)
+	value := newRsPoolValue(execInfo)
+
+	if _, ok := rp.rsMap[key]; !ok {
+		rp.rsList.PushFront(key)
+	} else {
+		rp.removeInList(key)
+		rp.rsList.PushFront(key)
+	}
+
+	rp.rsMap[key] = value
+	rp.totalDataLen += dataLen
+}
+
+func (rp *rsPool) get(stmt *DmStatement, sql string) (*rsPoolValue, error) {
+	key := newRsPoolKey(stmt, sql)
+
+	v, ok := rp.rsMap[key]
+	if ok {
+		b, err := v.refreshed(stmt.dmConn)
+		if err != nil {
+			return nil, err
+		}
+
+		if b {
+			rp.removeInList(key)
+			delete(rp.rsMap, key)
+			return nil, nil
+		}
+
+		rp.removeInList(key)
+		rp.rsList.PushFront(key)
+		return &v, nil
+	} else {
+		return nil, nil
+	}
+}
+
+func (s *DmStatement) Close() error {
+	if s.closed {
+		return nil
+	}
+	if len(s.filterChain.filters) == 0 {
+		return s.close()
+	}
+	return s.filterChain.reset().DmStatementClose(s)
+}
+
+func (s *DmStatement) NumInput() int {
+	if err := s.checkClosed(); err != nil {
+		return 0
+	}
+	if len(s.filterChain.filters) == 0 {
+		return s.numInput()
+	}
+	return s.filterChain.reset().DmStatementNumInput(s)
+}
+
+func (s *DmStatement) Exec(args []driver.Value) (driver.Result, error) {
+	if err := s.checkClosed(); err != nil {
+		return nil, err
+	}
+	if len(s.filterChain.filters) == 0 {
+		return s.exec(args)
+	}
+	return s.filterChain.reset().DmStatementExec(s, args)
+}
+
+func (s *DmStatement) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
+	if err := s.checkClosed(); err != nil {
+		return nil, err
+	}
+	if len(s.filterChain.filters) == 0 {
+		return s.execContext(ctx, args)
+	}
+	return s.filterChain.reset().DmStatementExecContext(s, ctx, args)
+}
+
+func (s *DmStatement) Query(args []driver.Value) (driver.Rows, error) {
+	if err := s.checkClosed(); err != nil {
+		return nil, err
+	}
+	if len(s.filterChain.filters) == 0 {
+		return s.query(args)
+	}
+	return s.filterChain.reset().DmStatementQuery(s, args)
+}
+
+func (s *DmStatement) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
+	if err := s.checkClosed(); err != nil {
+		return nil, err
+	}
+	if len(s.filterChain.filters) == 0 {
+		return s.queryContext(ctx, args)
+	}
+	return s.filterChain.reset().DmStatementQueryContext(s, ctx, args)
+}
+
+func (s *DmStatement) CheckNamedValue(nv *driver.NamedValue) error {
+	if len(s.filterChain.filters) == 0 {
+		return s.checkNamedValue(nv)
+	}
+	return s.filterChain.reset().DmStatementCheckNamedValue(s, nv)
+}
+
+func (st *DmStatement) prepare() error {
+	var err error
+	if st.dmConn.dmConnector.escapeProcess {
+		st.nativeSql, err = st.dmConn.escape(st.nativeSql, st.dmConn.dmConnector.keyWords)
+		if err != nil {
+			return err
+		}
+	}
+
+	st.execInfo, err = st.dmConn.Access.Dm_build_772(st, Dm_build_1057)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (stmt *DmStatement) close() error {
+	if stmt.closed {
+		return nil
+	}
+	stmt.inUse = true
+	if stmt.dmConn.stmtPool != nil && len(stmt.dmConn.stmtPool) < stmt.dmConn.dmConnector.stmtPoolMaxSize {
+		stmt.pool()
+		return nil
+	} else {
+		return stmt.free()
+	}
+}
+
+func (stmt *DmStatement) numInput() int {
+	return int(stmt.paramCount)
+}
+
+func (stmt *DmStatement) checkNamedValue(nv *driver.NamedValue) error {
+	var err error
+	var cvt = converter{stmt.dmConn, false}
+	nv.Value, err = cvt.ConvertValue(nv.Value)
+	stmt.isBatch = cvt.isBatch
+	return err
+}
+
+func (stmt *DmStatement) exec(args []driver.Value) (*DmResult, error) {
+	var err error
+
+	stmt.inUse = true
+	if stmt.isBatch && len(args) > 0 {
+		var tmpArg []driver.Value
+		var arg driver.Value
+		for i := len(args) - 1; i >= 0; i-- {
+			if args[i] != nil {
+				arg = args[i]
+				break
+			}
+		}
+		for _, row := range arg.([][]interface{}) {
+			tmpArg = append(tmpArg, row)
+		}
+		err = stmt.executeBatch(tmpArg)
+	} else {
+		err = stmt.executeInner(args, Dm_build_1059)
+	}
+	if err != nil {
+		return nil, err
+	}
+	return newDmResult(stmt, stmt.execInfo), nil
+}
+
+func (stmt *DmStatement) execContext(ctx context.Context, args []driver.NamedValue) (*DmResult, error) {
+	stmt.inUse = true
+	dargs, err := namedValueToValue(stmt, args)
+	if err != nil {
+		return nil, err
+	}
+
+	if err := stmt.dmConn.watchCancel(ctx); err != nil {
+		return nil, err
+	}
+	defer stmt.dmConn.finish()
+
+	return stmt.exec(dargs)
+}
+
+func (stmt *DmStatement) query(args []driver.Value) (*DmRows, error) {
+	var err error
+	stmt.inUse = true
+	err = stmt.executeInner(args, Dm_build_1058)
+	if err != nil {
+		return nil, err
+	}
+
+	if stmt.execInfo.hasResultSet {
+		return newDmRows(newInnerRows(0, stmt, stmt.execInfo)), nil
+	} else {
+		return newDmRows(newLocalInnerRows(stmt, nil, nil)), nil
+	}
+}
+
+func (stmt *DmStatement) queryContext(ctx context.Context, args []driver.NamedValue) (*DmRows, error) {
+	stmt.inUse = true
+	dargs, err := namedValueToValue(stmt, args)
+	if err != nil {
+		return nil, err
+	}
+
+	if err := stmt.dmConn.watchCancel(ctx); err != nil {
+		return nil, err
+	}
+	defer stmt.dmConn.finish()
+
+	rows, err := stmt.query(dargs)
+	if err != nil {
+		stmt.dmConn.finish()
+		return nil, err
+	}
+	rows.finish = stmt.dmConn.finish
+	return rows, err
+}
+
+func NewDmStmt(conn *DmConnection, sql string) (*DmStatement, error) {
+	var s *DmStatement
+
+	if s == nil {
+		s = new(DmStatement)
+		s.resetFilterable(&conn.filterable)
+		s.objId = -1
+		s.idGenerator = dmStmtIDGenerator
+		s.dmConn = conn
+		s.maxRows = int64(conn.dmConnector.maxRows)
+		s.nativeSql = sql
+		s.rsMap = make(map[int16]*innerRows)
+		s.inUse = true
+		s.isBatch = conn.isBatch
+
+		if conn.stmtPool != nil && len(conn.stmtPool) > 0 {
+			len := len(conn.stmtPool)
+			spi := conn.stmtPool[0]
+			copy(conn.stmtPool, conn.stmtPool[1:])
+			conn.stmtPool = conn.stmtPool[:len-1]
+			s.id = spi.id
+			s.cursorName = spi.cursorName
+			s.readBaseColName = spi.readBaseColName
+		} else {
+			err := conn.Access.Dm_build_754(s)
+			if err != nil {
+				return nil, err
+			}
+		}
+
+	}
+
+	return s, nil
+
+}
+
+func (stmt *DmStatement) checkClosed() error {
+	if stmt.dmConn.closed.IsSet() {
+		return driver.ErrBadConn
+	} else if stmt.closed {
+		return ECGO_STATEMENT_HANDLE_CLOSED.throw()
+	}
+
+	return nil
+}
+
+func (stmt *DmStatement) pool() {
+	for _, rs := range stmt.rsMap {
+		rs.Close()
+	}
+
+	stmt.dmConn.stmtPool = append(stmt.dmConn.stmtPool, stmtPoolInfo{stmt.id, stmt.cursorName, stmt.readBaseColName})
+	delete(stmt.dmConn.stmtMap, stmt.id)
+	stmt.inUse = false
+	stmt.closed = true
+}
+
+func (stmt *DmStatement) free() error {
+	for _, rs := range stmt.rsMap {
+		rs.Close()
+	}
+
+	err := stmt.dmConn.Access.Dm_build_759(int32(stmt.id))
+	if err != nil {
+		return err
+	}
+	delete(stmt.dmConn.stmtMap, stmt.id)
+	stmt.inUse = false
+	stmt.closed = true
+	return nil
+}
+
+func bindInParam(stmt *DmStatement, i int, dtype int32, firstRow bool) {
+	if !firstRow {
+		return
+	}
+	isNil := dtype == NULL
+	serverParam := &stmt.serverParams[i]
+	bindParam := &stmt.bindParams[i]
+	if serverParam == nil {
+		bindParam.resetType(dtype)
+	} else {
+		bindParam.name = serverParam.name
+		bindParam.typeDescriptor = serverParam.typeDescriptor
+		bindParam.mask = serverParam.mask
+		bindParam.typeFlag = serverParam.typeFlag
+
+		if (serverParam.colType != UNKNOWN && (isNil || serverParam.typeFlag == TYPE_FLAG_EXACT)) || serverParam.mask != 0 {
+
+			bindParam.colType = serverParam.colType
+			bindParam.prec = serverParam.prec
+			bindParam.scale = serverParam.scale
+			bindParam.mask = serverParam.mask
+		} else {
+
+			bindParam.resetType(dtype)
+		}
+	}
+
+	if bindParam.ioType == IO_TYPE_OUT || bindParam.ioType == IO_TYPE_INOUT {
+		bindParam.ioType = IO_TYPE_INOUT
+	} else {
+		bindParam.ioType = IO_TYPE_IN
+	}
+}
+
+func checkBindParameters(stmt *DmStatement, bytes []interface{}) error {
+
+	for i := 0; int32(i) < stmt.paramCount; i++ {
+		if stmt.bindParams[i].ioType == IO_TYPE_UNKNOWN {
+
+			if stmt.serverParams[i].ioType == IO_TYPE_OUT {
+
+				bytes[i] = nil
+			} else {
+				return ECGO_UNBINDED_PARAMETER.throw()
+			}
+		}
+
+		if stmt.bindParams[i].colType == CURSOR {
+			stmt.bindParams[i].ioType = IO_TYPE_INOUT
+			continue
+		}
+
+		if stmt.serverParams[i].ioType != stmt.bindParams[i].ioType {
+
+			stmt.bindParams[i].ioType = stmt.serverParams[i].ioType
+		}
+	}
+
+	for i := 0; int32(i) < stmt.paramCount; i++ {
+		if stmt.bindParams[i].ioType == IO_TYPE_INOUT || stmt.bindParams[i].ioType == IO_TYPE_OUT {
+			continue
+		}
+		switch stmt.bindParams[i].colType {
+		case CHAR, VARCHAR, VARCHAR2:
+			length := -1
+			if b, ok := bytes[i].([]byte); ok {
+				length = len(b)
+			}
+			if length > VARCHAR_PREC {
+				return ECGO_STRING_CUT.throw()
+			}
+			if length > int(stmt.bindParams[i].prec) {
+				if length < VARCHAR_PREC/4 {
+					stmt.bindParams[i].prec = VARCHAR_PREC / 4
+				} else if length < VARCHAR_PREC/2 {
+					stmt.bindParams[i].prec = VARCHAR_PREC / 2
+				} else if length < VARCHAR_PREC*3/4 {
+					stmt.bindParams[i].prec = VARCHAR_PREC * 3 / 4
+				} else {
+					stmt.bindParams[i].prec = VARCHAR_PREC
+				}
+			}
+		}
+	}
+	return nil
+}
+
+func bindOutParam(stmt *DmStatement, i int, dtype int32) error {
+	var err error
+	serverParam := &stmt.serverParams[i]
+	bindParam := &stmt.bindParams[i]
+
+	if bindParam.ioType == IO_TYPE_OUT || bindParam.ioType == IO_TYPE_UNKNOWN {
+
+		if serverParam == nil {
+
+			bindParam.resetType(dtype)
+		} else {
+
+			bindParam.name = serverParam.name
+			bindParam.typeDescriptor = serverParam.typeDescriptor
+			bindParam.mask = serverParam.mask
+			bindParam.typeFlag = serverParam.typeFlag
+
+			if (serverParam.colType != UNKNOWN && serverParam.typeFlag == TYPE_FLAG_EXACT) || serverParam.mask != 0 {
+
+				bindParam.colType = serverParam.colType
+				bindParam.prec = serverParam.prec
+				bindParam.scale = serverParam.scale
+				bindParam.mask = serverParam.mask
+			} else {
+
+				bindParam.resetType(dtype)
+			}
+		}
+
+		if bindParam.colType == CURSOR {
+			bindParam.ioType = IO_TYPE_INOUT
+			if bindParam.cursorStmt == nil {
+				bindParam.cursorStmt = &DmStatement{dmConn: stmt.dmConn}
+				bindParam.cursorStmt.resetFilterable(&stmt.dmConn.filterable)
+				err = bindParam.cursorStmt.dmConn.Access.Dm_build_754(bindParam.cursorStmt)
+			}
+		}
+	}
+
+	if bindParam.ioType == IO_TYPE_IN || bindParam.ioType == IO_TYPE_INOUT {
+		bindParam.ioType = IO_TYPE_INOUT
+	} else {
+		bindParam.ioType = IO_TYPE_OUT
+	}
+
+	return err
+}
+
+func encodeArgs(stmt *DmStatement, args []driver.Value, firstRow bool) ([]interface{}, error) {
+	bytes := make([]interface{}, len(args), len(args))
+
+	var err error
+
+	for i, arg := range args {
+	nextSwitch:
+		if stmt.serverParams[i].colType == CURSOR {
+			bindInParam(stmt, i, CURSOR, firstRow)
+			if stmt.bindParams[i].cursorStmt == nil {
+				stmt.bindParams[i].cursorStmt = &DmStatement{dmConn: stmt.dmConn}
+				stmt.bindParams[i].cursorStmt.resetFilterable(&stmt.dmConn.filterable)
+				err = stmt.bindParams[i].cursorStmt.dmConn.Access.Dm_build_754(stmt.bindParams[i].cursorStmt)
+			}
+			stmt.bindParams[i].ioType = IO_TYPE_INOUT
+			continue
+		}
+		if arg == nil {
+			bindInParam(stmt, i, NULL, firstRow)
+			bytes[i] = nil
+
+			continue
+		}
+
+		switch v := arg.(type) {
+		case bool:
+			bindInParam(stmt, i, TINYINT, firstRow)
+			bytes[i], err = G2DB.fromBool(v, stmt.bindParams[i], stmt.dmConn)
+		case int8:
+			bindInParam(stmt, i, TINYINT, firstRow)
+			bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn)
+		case int16:
+			bindInParam(stmt, i, SMALLINT, firstRow)
+			bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn)
+		case int32:
+			bindInParam(stmt, i, INT, firstRow)
+			bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn)
+		case int64:
+			bindInParam(stmt, i, BIGINT, firstRow)
+			bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn)
+		case int:
+			bindInParam(stmt, i, BIGINT, firstRow)
+			bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn)
+		case uint8:
+			bindInParam(stmt, i, SMALLINT, firstRow)
+			bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn)
+		case uint16:
+			bindInParam(stmt, i, INT, firstRow)
+			bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn)
+		case uint32:
+			bindInParam(stmt, i, BIGINT, firstRow)
+			bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn)
+
+		case float32:
+			bindInParam(stmt, i, REAL, firstRow)
+			bytes[i], err = G2DB.fromFloat32(v, stmt.bindParams[i], stmt.dmConn)
+		case float64:
+			bindInParam(stmt, i, DOUBLE, firstRow)
+			bytes[i], err = G2DB.fromFloat64(float64(v), stmt.bindParams[i], stmt.dmConn)
+		case []byte:
+			if v == nil {
+				bindInParam(stmt, i, NULL, firstRow)
+				bytes[i] = nil
+
+			} else {
+				dtype := VARBINARY
+				if len(v) >= VARBINARY_PREC {
+					dtype = BLOB
+				}
+				bindInParam(stmt, i, int32(dtype), firstRow)
+				bytes[i], err = G2DB.fromBytes(v, stmt.bindParams[i], stmt.dmConn)
+			}
+		case string:
+
+			if v == "" && emptyStringToNil(stmt.serverParams[i].colType) {
+				arg = nil
+				goto nextSwitch
+			}
+			dtype := VARCHAR
+			if len(v) >= VARCHAR_PREC {
+				dtype = CLOB
+			}
+			bindInParam(stmt, i, int32(dtype), firstRow)
+			bytes[i], err = G2DB.fromString(v, stmt.bindParams[i], stmt.dmConn)
+		case time.Time:
+			bindInParam(stmt, i, DATETIME, firstRow)
+			bytes[i], err = G2DB.fromTime(v, stmt.bindParams[i], stmt.dmConn)
+		case DmTimestamp:
+			bindInParam(stmt, i, DATETIME, firstRow)
+			bytes[i], err = G2DB.fromTime(v.ToTime(), stmt.bindParams[i], stmt.dmConn)
+		case DmIntervalDT:
+			bindInParam(stmt, i, INTERVAL_DT, firstRow)
+			if stmt.bindParams[i].typeFlag != TYPE_FLAG_EXACT {
+				stmt.bindParams[i].scale = int32(v.scaleForSvr)
+			}
+			bytes[i], err = G2DB.fromDmIntervalDT(v, stmt.bindParams[i], stmt.dmConn)
+		case DmIntervalYM:
+			bindInParam(stmt, i, INTERVAL_YM, firstRow)
+			if stmt.bindParams[i].typeFlag != TYPE_FLAG_EXACT {
+				stmt.bindParams[i].scale = int32(v.scaleForSvr)
+			}
+			bytes[i], err = G2DB.fromDmdbIntervalYM(v, stmt.bindParams[i], stmt.dmConn)
+		case DmDecimal:
+			bindInParam(stmt, i, DECIMAL, firstRow)
+			bytes[i], err = G2DB.fromDecimal(v, stmt.bindParams[i], stmt.dmConn)
+
+		case DmBlob:
+			bindInParam(stmt, i, BLOB, firstRow)
+			bytes[i], err = G2DB.fromBlob(DmBlob(v), stmt.bindParams[i], stmt.dmConn)
+			if err != nil {
+				return nil, err
+			}
+		case DmClob:
+			bindInParam(stmt, i, CLOB, firstRow)
+			bytes[i], err = G2DB.fromClob(DmClob(v), stmt.bindParams[i], stmt.dmConn)
+			if err != nil {
+				return nil, err
+			}
+		case DmArray:
+			bindInParam(stmt, i, ARRAY, firstRow)
+			da := &v
+			da, err = da.create(stmt.dmConn)
+			if err != nil {
+				return nil, err
+			}
+
+			bytes[i], err = G2DB.fromArray(da, stmt.bindParams[i], stmt.dmConn)
+		case DmStruct:
+			bindInParam(stmt, i, CLASS, firstRow)
+			ds := &v
+			ds, err = ds.create(stmt.dmConn)
+			if err != nil {
+				return nil, err
+			}
+
+			bytes[i], err = G2DB.fromStruct(ds, stmt.bindParams[i], stmt.dmConn)
+		case sql.Out:
+			var cvt = converter{stmt.dmConn, false}
+			if arg, err = cvt.ConvertValue(v.Dest); err != nil {
+				return nil, err
+			}
+			goto nextSwitch
+
+		case *DmTimestamp:
+			bindInParam(stmt, i, DATETIME, firstRow)
+			bytes[i], err = G2DB.fromTime(v.ToTime(), stmt.bindParams[i], stmt.dmConn)
+		case *DmIntervalDT:
+			bindInParam(stmt, i, INTERVAL_DT, firstRow)
+			if stmt.bindParams[i].typeFlag != TYPE_FLAG_EXACT {
+				stmt.bindParams[i].scale = int32(v.scaleForSvr)
+			}
+			bytes[i], err = G2DB.fromDmIntervalDT(*v, stmt.bindParams[i], stmt.dmConn)
+		case *DmIntervalYM:
+			bindInParam(stmt, i, INTERVAL_YM, firstRow)
+			if stmt.bindParams[i].typeFlag != TYPE_FLAG_EXACT {
+				stmt.bindParams[i].scale = int32(v.scaleForSvr)
+			}
+			bytes[i], err = G2DB.fromDmdbIntervalYM(*v, stmt.bindParams[i], stmt.dmConn)
+		case *DmDecimal:
+			bindInParam(stmt, i, DECIMAL, firstRow)
+			bytes[i], err = G2DB.fromDecimal(*v, stmt.bindParams[i], stmt.dmConn)
+		case *DmBlob:
+			bindInParam(stmt, i, BLOB, firstRow)
+			bytes[i], err = G2DB.fromBlob(DmBlob(*v), stmt.bindParams[i], stmt.dmConn)
+		case *DmClob:
+			bindInParam(stmt, i, CLOB, firstRow)
+			bytes[i], err = G2DB.fromClob(DmClob(*v), stmt.bindParams[i], stmt.dmConn)
+		case *DmArray:
+			bindInParam(stmt, i, ARRAY, firstRow)
+			v, err = v.create(stmt.dmConn)
+			if err != nil {
+				return nil, err
+			}
+
+			bytes[i], err = G2DB.fromArray(v, stmt.bindParams[i], stmt.dmConn)
+		case *DmStruct:
+			bindInParam(stmt, i, CLASS, firstRow)
+			v, err = v.create(stmt.dmConn)
+			if err != nil {
+				return nil, err
+			}
+
+			bytes[i], err = G2DB.fromStruct(v, stmt.bindParams[i], stmt.dmConn)
+		case *driver.Rows:
+			if stmt.serverParams[i].colType == CURSOR {
+				bindInParam(stmt, i, CURSOR, firstRow)
+				if stmt.bindParams[i].cursorStmt == nil {
+					stmt.bindParams[i].cursorStmt = &DmStatement{dmConn: stmt.dmConn}
+					stmt.bindParams[i].cursorStmt.resetFilterable(&stmt.dmConn.filterable)
+					err = stmt.bindParams[i].cursorStmt.dmConn.Access.Dm_build_754(stmt.bindParams[i].cursorStmt)
+				}
+			}
+		case io.Reader:
+			bindInParam(stmt, i, stmt.serverParams[i].colType, firstRow)
+			bytes[i], err = G2DB.fromReader(io.Reader(v), stmt.serverParams[i], stmt.dmConn)
+			if err != nil {
+				return nil, err
+			}
+		default:
+			err = ECGO_UNSUPPORTED_INPARAM_TYPE.throw()
+		}
+
+		if err != nil {
+			return nil, err
+		}
+
+	}
+	checkBindParameters(stmt, bytes)
+
+	return bytes, nil
+}
+
+type converter struct {
+	conn    *DmConnection
+	isBatch bool
+}
+type decimalDecompose interface {
+	Decompose(buf []byte) (form byte, negative bool, coefficient []byte, exponent int32)
+}
+
+func (c *converter) ConvertValue(v interface{}) (driver.Value, error) {
+	if driver.IsValue(v) {
+		return v, nil
+	}
+
+	switch vr := v.(type) {
+	case driver.Valuer:
+		sv, err := callValuerValue(vr)
+		if err != nil {
+			return nil, err
+		}
+
+		return sv, nil
+
+	case decimalDecompose, DmDecimal, *DmDecimal, DmTimestamp, *DmTimestamp, DmIntervalDT, *DmIntervalDT,
+		DmIntervalYM, *DmIntervalYM, driver.Rows, *driver.Rows, DmArray, *DmArray, DmStruct, *DmStruct, sql.Out:
+		return vr, nil
+	case big.Int:
+		return NewDecimalFromBigInt(&vr)
+	case big.Float:
+		return NewDecimalFromBigFloat(&vr)
+	case DmClob:
+
+		if vr.connection == nil {
+			vr.connection = c.conn
+		}
+		return vr, nil
+	case *DmClob:
+
+		if vr.connection == nil {
+			vr.connection = c.conn
+		}
+		return vr, nil
+	case DmBlob:
+
+		if vr.connection == nil {
+			vr.connection = c.conn
+		}
+		return vr, nil
+	case *DmBlob:
+
+		if vr.connection == nil {
+			vr.connection = c.conn
+		}
+		return vr, nil
+	case io.Reader:
+		return vr, nil
+	}
+
+	rv := reflect.ValueOf(v)
+	switch rv.Kind() {
+	case reflect.Ptr:
+		if rv.IsNil() {
+			return nil, nil
+		} else {
+			return c.ConvertValue(rv.Elem().Interface())
+		}
+	case reflect.Int:
+		return rv.Int(), nil
+	case reflect.Int8:
+		return int8(rv.Int()), nil
+	case reflect.Int16:
+		return int16(rv.Int()), nil
+	case reflect.Int32:
+		return int32(rv.Int()), nil
+	case reflect.Int64:
+		return int64(rv.Int()), nil
+	case reflect.Uint8:
+		return uint8(rv.Uint()), nil
+	case reflect.Uint16:
+		return uint16(rv.Uint()), nil
+	case reflect.Uint32:
+		return uint32(rv.Uint()), nil
+	case reflect.Uint64, reflect.Uint:
+		u64 := rv.Uint()
+		if u64 >= 1<<63 {
+			bigInt := &big.Int{}
+			bigInt.SetString(strconv.FormatUint(u64, 10), 10)
+			return NewDecimalFromBigInt(bigInt)
+		}
+		return int64(u64), nil
+	case reflect.Float32:
+		return float32(rv.Float()), nil
+	case reflect.Float64:
+		return float64(rv.Float()), nil
+	case reflect.Bool:
+		return rv.Bool(), nil
+	case reflect.Slice:
+		ek := rv.Type().Elem().Kind()
+		if ek == reflect.Uint8 {
+			return rv.Bytes(), nil
+		} else if ek == reflect.Slice {
+			c.isBatch = true
+			return v, nil
+		}
+		return nil, fmt.Errorf("unsupported type %T, a slice of %s", v, ek)
+	case reflect.String:
+		return rv.String(), nil
+	}
+	return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
+}
+
+var valuerReflectType = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
+
+func callValuerValue(vr driver.Valuer) (v driver.Value, err error) {
+	if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Ptr &&
+		rv.IsNil() &&
+		rv.Type().Elem().Implements(valuerReflectType) {
+		return nil, nil
+	}
+	return vr.Value()
+}
+
+func namedValueToValue(stmt *DmStatement, named []driver.NamedValue) ([]driver.Value, error) {
+
+	dargs := make([]driver.Value, stmt.paramCount)
+	for i, _ := range dargs {
+		found := false
+		for _, nv := range named {
+			if nv.Name != "" && strings.ToUpper(nv.Name) == strings.ToUpper(stmt.serverParams[i].name) {
+				dargs[i] = nv.Value
+				found = true
+				break
+			}
+		}
+
+		if !found && i < len(named) {
+			dargs[i] = named[i].Value
+		}
+
+	}
+	return dargs, nil
+}
+
+func (stmt *DmStatement) executeInner(args []driver.Value, executeType int16) (err error) {
+
+	var bytes []interface{}
+
+	if stmt.paramCount > 0 {
+		bytes, err = encodeArgs(stmt, args, true)
+		if err != nil {
+			return err
+		}
+	}
+	stmt.execInfo, err = stmt.dmConn.Access.Dm_build_804(stmt, bytes, false)
+	if err != nil {
+		return err
+	}
+	if stmt.execInfo.outParamDatas != nil {
+		for i, outParamData := range stmt.execInfo.outParamDatas {
+			if stmt.bindParams[i].ioType == IO_TYPE_IN || stmt.bindParams[i].ioType == IO_TYPE_UNKNOWN {
+				continue
+			}
+
+			var v sql.Out
+			ok := true
+			for ok {
+				if v, ok = args[i].(sql.Out); ok {
+					args[i] = v.Dest
+				}
+			}
+
+			if sc, ok := args[i].(sql.Scanner); ok {
+				var v interface{}
+				if outParamData == nil && stmt.bindParams[i].colType != CURSOR {
+					v = nil
+					if err = sc.Scan(v); err != nil {
+						return err
+					}
+					continue
+				}
+
+				switch stmt.bindParams[i].colType {
+				case BOOLEAN:
+					v, err = DB2G.toBool(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case BIT:
+					if strings.ToLower(stmt.bindParams[i].typeName) == "boolean" {
+						v, err = DB2G.toBool(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+					}
+
+					v, err = DB2G.toInt8(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case TINYINT:
+					v, err = DB2G.toInt8(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case SMALLINT:
+					v, err = DB2G.toInt16(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case INT:
+					v, err = DB2G.toInt32(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case BIGINT:
+					v, err = DB2G.toInt64(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case REAL:
+					v, err = DB2G.toFloat32(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case DOUBLE:
+					v, err = DB2G.toFloat64(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case DATE, TIME, DATETIME, TIME_TZ, DATETIME_TZ, DATETIME2, DATETIME2_TZ:
+					v, err = DB2G.toTime(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case INTERVAL_DT:
+					v = newDmIntervalDTByBytes(outParamData)
+				case INTERVAL_YM:
+					v = newDmIntervalYMByBytes(outParamData)
+				case DECIMAL:
+					v, err = DB2G.toDmDecimal(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case BINARY, VARBINARY:
+					v = util.StringUtil.BytesToHexString(outParamData, false)
+				case BLOB:
+					v = DB2G.toDmBlob(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case CHAR, VARCHAR2, VARCHAR:
+					v = DB2G.toString(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case CLOB:
+					v = DB2G.toDmClob(outParamData, stmt.dmConn, &stmt.bindParams[i].column)
+				case ARRAY:
+					v, err = TypeDataSV.bytesToArray(outParamData, nil, stmt.bindParams[i].typeDescriptor)
+				case CLASS:
+					v, err = TypeDataSV.bytesToObj(outParamData, nil, stmt.bindParams[i].typeDescriptor)
+				case CURSOR:
+					var tmpExecInfo *execRetInfo
+					if tmpExecInfo, err = stmt.dmConn.Access.Dm_build_814(stmt.bindParams[i].cursorStmt, 1); err != nil {
+						return err
+					}
+					if tmpExecInfo.hasResultSet {
+						v = newDmRows(newInnerRows(0, stmt.bindParams[i].cursorStmt, tmpExecInfo))
+					}
+				default:
+					err = ECGO_UNSUPPORTED_OUTPARAM_TYPE.throw()
+				}
+				if err == nil {
+					err = sc.Scan(v)
+				}
+			} else if args[i] == nil {
+				if outParamData == nil && stmt.bindParams[i].colType != CURSOR {
+					continue
+				}
+
+				switch stmt.bindParams[i].colType {
+				case BOOLEAN:
+					args[i], err = DB2G.toBool(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case BIT:
+					if strings.ToLower(stmt.bindParams[i].typeName) == "boolean" {
+						args[i], err = DB2G.toBool(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+					}
+
+					args[i], err = DB2G.toInt8(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case TINYINT:
+					args[i], err = DB2G.toInt8(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case SMALLINT:
+					args[i], err = DB2G.toInt16(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case INT:
+					args[i], err = DB2G.toInt32(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case BIGINT:
+					args[i], err = DB2G.toInt64(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case REAL:
+					args[i], err = DB2G.toFloat32(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case DOUBLE:
+					args[i], err = DB2G.toFloat64(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case DATE, TIME, DATETIME, TIME_TZ, DATETIME_TZ, DATETIME2, DATETIME2_TZ:
+					args[i], err = DB2G.toTime(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case INTERVAL_DT:
+					args[i] = newDmIntervalDTByBytes(outParamData)
+				case INTERVAL_YM:
+					args[i] = newDmIntervalYMByBytes(outParamData)
+				case DECIMAL:
+					args[i], err = DB2G.toDmDecimal(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case BINARY, VARBINARY:
+					args[i] = util.StringUtil.BytesToHexString(outParamData, false)
+				case BLOB:
+					args[i] = DB2G.toDmBlob(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case CHAR, VARCHAR2, VARCHAR:
+					args[i] = DB2G.toString(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+				case CLOB:
+					args[i] = DB2G.toDmClob(outParamData, stmt.dmConn, &stmt.bindParams[i].column)
+				default:
+					err = ECGO_UNSUPPORTED_OUTPARAM_TYPE.throw()
+				}
+			} else {
+				switch v := args[i].(type) {
+				case *string:
+					if outParamData == nil {
+						*v = ""
+					} else {
+						*v = DB2G.toString(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+					}
+				case *sql.NullString:
+					if outParamData == nil {
+						v.String = ""
+						v.Valid = false
+					} else {
+						v.String = DB2G.toString(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+						v.Valid = true
+					}
+				case *[]byte:
+					if outParamData == nil {
+						*v = nil
+					} else {
+						var val []byte
+						if val, err = DB2G.toBytes(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
+							return err
+						}
+						*v = val
+					}
+				case *bool:
+					if outParamData == nil {
+						*v = false
+					} else {
+						var val bool
+						if val, err = DB2G.toBool(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
+							return err
+						}
+						*v = val
+					}
+				case *sql.NullBool:
+					if outParamData == nil {
+						v.Bool = false
+						v.Valid = false
+					} else {
+						var val bool
+						if val, err = DB2G.toBool(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
+							return err
+						}
+						v.Bool = val
+						v.Valid = true
+					}
+				case *int8:
+					if outParamData == nil {
+						*v = 0
+					} else {
+						var val int8
+						if val, err = DB2G.toInt8(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
+							return err
+						}
+						*v = val
+					}
+				case *int16:
+					if outParamData == nil {
+						*v = 0
+					} else {
+						var val int16
+						if val, err = DB2G.toInt16(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
+							return err
+						}
+						*v = val
+					}
+				case *int32:
+					if outParamData == nil {
+						*v = 0
+					} else {
+						var val int32
+						if val, err = DB2G.toInt32(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
+							return err
+						}
+						*v = val
+					}
+				case *sql.NullInt32:
+					if outParamData == nil {
+						v.Int32 = 0
+						v.Valid = false
+					} else {
+						var val int32
+						if val, err = DB2G.toInt32(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
+							return err
+						}
+						v.Int32 = val
+						v.Valid = true
+					}
+				case *int64:
+					if outParamData == nil {
+						*v = 0
+					} else {
+						var val int64
+						if val, err = DB2G.toInt64(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
+							return err
+						}
+						*v = val
+					}
+				case *sql.NullInt64:
+					if outParamData == nil {
+						v.Int64 = 0
+						v.Valid = false
+					} else {
+						var val int64
+						if val, err = DB2G.toInt64(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
+							return err
+						}
+						v.Int64 = val
+						v.Valid = true
+					}
+				case *uint8:
+					if outParamData == nil {
+						*v = 0
+					} else {
+						var val uint8
+						if val, err = DB2G.toByte(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
+							return err
+						}
+						*v = val
+					}
+				case *uint16:
+					if outParamData == nil {
+						*v = 0
+					} else {
+						var val uint16
+						if val, err = DB2G.toUInt16(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
+							return err
+						}
+						*v = val
+					}
+				case *uint32:
+					if outParamData == nil {
+						*v = 0
+					} else {
+						var val uint32
+						if val, err = DB2G.toUInt32(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
+							return err
+						}
+						*v = val
+					}
+				case *uint64:
+					if outParamData == nil {
+						*v = 0
+					} else {
+						var val uint64
+						if val, err = DB2G.toUInt64(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
+							return err
+						}
+						*v = val
+					}
+				case *int:
+					if outParamData == nil {
+						*v = 0
+					} else {
+						var val int
+						if val, err = DB2G.toInt(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
+							return err
+						}
+						*v = val
+					}
+				case *uint:
+					if outParamData == nil {
+						*v = 0
+					} else {
+						var val uint
+						if val, err = DB2G.toUInt(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
+							return err
+						}
+						*v = val
+					}
+				case *float32:
+					if outParamData == nil {
+						*v = 0.0
+					} else {
+						var val float32
+						if val, err = DB2G.toFloat32(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
+							return err
+						}
+						*v = val
+					}
+				case *float64:
+					if outParamData == nil {
+						*v = 0.0
+					} else {
+						var val float64
+						if val, err = DB2G.toFloat64(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
+							return err
+						}
+						*v = val
+					}
+				case *sql.NullFloat64:
+					if outParamData == nil {
+						v.Float64 = 0.0
+						v.Valid = false
+					} else {
+						var val float64
+						if val, err = DB2G.toFloat64(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
+							return err
+						}
+						v.Float64 = val
+						v.Valid = true
+					}
+				case *time.Time:
+					if outParamData == nil {
+						*v = time.Time{}
+					} else {
+						var val time.Time
+						if val, err = DB2G.toTime(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
+							return err
+						}
+						*v = val
+					}
+				case *sql.NullTime:
+					if outParamData == nil {
+						v.Time = time.Time{}
+						v.Valid = false
+					} else {
+						var val time.Time
+						if val, err = DB2G.toTime(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
+							return err
+						}
+						v.Time = val
+						v.Valid = true
+					}
+				case *DmTimestamp:
+					if outParamData == nil {
+						*v = DmTimestamp{}
+					} else {
+						*v = *newDmTimestampFromBytes(outParamData, stmt.bindParams[i].column, stmt.dmConn)
+					}
+				case *DmIntervalDT:
+					if outParamData == nil {
+						*v = DmIntervalDT{}
+					} else {
+						*v = *newDmIntervalDTByBytes(outParamData)
+					}
+				case *DmIntervalYM:
+					if outParamData == nil {
+						*v = DmIntervalYM{}
+					} else {
+						*v = *newDmIntervalYMByBytes(outParamData)
+					}
+				case *DmDecimal:
+					if outParamData == nil {
+						*v = DmDecimal{}
+					} else {
+						var val *DmDecimal
+						if val, err = DB2G.toDmDecimal(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
+							return err
+						}
+						*v = *val
+					}
+				case *DmBlob:
+					if outParamData == nil {
+						*v = DmBlob{}
+					} else {
+						*v = *DB2G.toDmBlob(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
+					}
+				case *DmClob:
+					if outParamData == nil {
+						*v = DmClob{}
+					} else {
+						*v = *DB2G.toDmClob(outParamData, stmt.dmConn, &stmt.bindParams[i].column)
+					}
+				case *driver.Rows:
+					if stmt.bindParams[i].colType == CURSOR {
+						var tmpExecInfo *execRetInfo
+						tmpExecInfo, err = stmt.dmConn.Access.Dm_build_814(stmt.bindParams[i].cursorStmt, 1)
+						if err != nil {
+							return err
+						}
+
+						if tmpExecInfo.hasResultSet {
+							*v = newDmRows(newInnerRows(0, stmt.bindParams[i].cursorStmt, tmpExecInfo))
+						} else {
+							*v = nil
+						}
+					}
+				case *DmArray:
+					if outParamData == nil {
+						*v = DmArray{}
+					} else {
+						var val *DmArray
+						if val, err = TypeDataSV.bytesToArray(outParamData, nil, stmt.bindParams[i].typeDescriptor); err != nil {
+							return err
+						}
+						*v = *val
+					}
+				case *DmStruct:
+					if outParamData == nil {
+						*v = DmStruct{}
+					} else {
+						var tmp interface{}
+						if tmp, err = TypeDataSV.bytesToObj(outParamData, nil, stmt.bindParams[i].typeDescriptor); err != nil {
+							return err
+						}
+						if val, ok := tmp.(*DmStruct); ok {
+							*v = *val
+						}
+					}
+				default:
+					err = ECGO_UNSUPPORTED_OUTPARAM_TYPE.throw()
+				}
+			}
+			if err != nil {
+				return err
+			}
+		}
+
+	}
+	return err
+}
+
+func (stmt *DmStatement) executeBatch(args []driver.Value) (err error) {
+
+	var bytes [][]interface{}
+
+	if stmt.execInfo.retSqlType == Dm_build_1072 || stmt.execInfo.retSqlType == Dm_build_1077 {
+		return ECGO_INVALID_SQL_TYPE.throw()
+	}
+
+	if stmt.paramCount > 0 && args != nil && len(args) > 0 {
+
+		if len(args) == 1 || stmt.dmConn.dmConnector.batchType == 2 ||
+			(stmt.dmConn.dmConnector.batchNotOnCall && stmt.execInfo.retSqlType == Dm_build_1073) {
+			return stmt.executeBatchByRow(args)
+		} else {
+			for i, arg := range args {
+				var newArg []driver.Value
+				for _, a := range arg.([]interface{}) {
+					newArg = append(newArg, a)
+				}
+				tmpBytes, err := encodeArgs(stmt, newArg, i == 0)
+				if err != nil {
+					return err
+				}
+				bytes = append(bytes, tmpBytes)
+			}
+			stmt.execInfo, err = stmt.dmConn.Access.Dm_build_793(stmt, bytes, stmt.preExec)
+		}
+	}
+	return err
+}
+
+func (stmt *DmStatement) executeBatchByRow(args []driver.Value) (err error) {
+	count := len(args)
+	stmt.execInfo = NewExceInfo()
+	stmt.execInfo.updateCounts = make([]int64, count)
+	var sqlErrBuilder strings.Builder
+	for i := 0; i < count; i++ {
+		tmpExecInfo, err := stmt.dmConn.Access.Dm_build_804(stmt, args[i].([]interface{}), stmt.preExec || i != 0)
+		if err == nil {
+			stmt.execInfo.union(tmpExecInfo, i, 1)
+		} else {
+			stmt.execInfo.updateCounts[i] = -1
+			if stmt.dmConn.dmConnector.continueBatchOnError {
+				sqlErrBuilder.WriteString("row[" + strconv.Itoa(i) + "]:" + err.Error() + util.LINE_SEPARATOR)
+			} else {
+				return ECGO_BATCH_ERROR.addDetailln(err.Error()).throw()
+			}
+		}
+	}
+	if sqlErrBuilder.Len() > 0 {
+		return EC_BP_WITH_ERROR.addDetail(sqlErrBuilder.String()).throw()
+	}
+	return nil
+}

+ 38 - 0
util/zzq.go

@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package util
+
+func Split(s string, sep string) []string {
+	var foot = make([]int, len(s)) // 足够的元素个数
+	var count, sLen, sepLen = 0, len(s), len(sep)
+	for i := 0; i < sLen; i++ {
+		// 处理 s == “-9999-1" && seperators == "-"情况
+		if i == 0 && sLen >= sepLen {
+			if s[0:sepLen] == sep {
+				i += sepLen - 1
+				continue
+			}
+		}
+		for j := 0; j < sepLen; j++ {
+			if s[i] == sep[j] {
+				foot[count] = i
+				count++
+				break
+			}
+		}
+	}
+	var ret = make([]string, count+1)
+	if count == 0 {
+		ret[0] = s
+		return ret
+	}
+	ret[0] = s[0:foot[0]]
+	for i := 1; i < count; i++ {
+		ret[i] = s[foot[i-1]+1 : foot[i]]
+	}
+	ret[count] = s[foot[count-1]+1:]
+	return ret
+}

+ 75 - 0
util/zzr.go

@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package util
+
+import (
+	"go/build"
+	"os"
+	"runtime"
+	"strings"
+)
+
+const (
+	PathSeparator     = string(os.PathSeparator)
+	PathListSeparator = string(os.PathListSeparator)
+)
+
+var (
+	goRoot = build.Default.GOROOT
+	goPath = build.Default.GOPATH //获取实际编译时的GOPATH值
+)
+
+type fileUtil struct {
+}
+
+var FileUtil = &fileUtil{}
+
+func (fileUtil *fileUtil) Exists(path string) bool {
+	if _, err := os.Stat(path); !os.IsNotExist(err) {
+		return true
+	}
+	return false
+}
+
+func (fileUtil *fileUtil) Search(relativePath string) (path string) {
+	if strings.Contains(runtime.GOOS, "windows") {
+		relativePath = strings.ReplaceAll(relativePath, "/", "\\")
+	}
+
+	if fileUtil.Exists(goPath) {
+		for _, s := range strings.Split(goPath, PathListSeparator) {
+			path = s + PathSeparator + "src" + PathSeparator + relativePath
+			if fileUtil.Exists(path) {
+				return path
+			}
+		}
+	}
+
+	if fileUtil.Exists(goPath) {
+		for _, s := range strings.Split(goPath, PathListSeparator) {
+			path = s + PathSeparator + "pkg" + PathSeparator + relativePath
+			if fileUtil.Exists(path) {
+				return path
+			}
+		}
+	}
+
+	//if workDir, _ := os.Getwd(); fileUtil.Exists(workDir) {
+	//	path = workDir + PathSeparator + "src" + PathSeparator + relativePath
+	//	if fileUtil.Exists(path) {
+	//		return path
+	//	}
+	//}
+
+	//if fileUtil.Exists(goRoot) {
+	//	path = goRoot + PathSeparator + "src" + PathSeparator + relativePath
+	//	if fileUtil.Exists(path) {
+	//		return path
+	//	}
+	//}
+
+	return ""
+}

+ 47 - 0
util/zzs.go

@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package util
+
+const (
+	LINE_SEPARATOR = "\n"
+)
+
+func SliceEquals(src []byte, dest []byte) bool {
+	if len(src) != len(dest) {
+		return false
+	}
+
+	for i, _ := range src {
+		if src[i] != dest[i] {
+			return false
+		}
+	}
+
+	return true
+}
+
+// 获取两个数的最大公约数,由调用者确保m、n>=0;如果m或n为0,返回1
+func GCD(m int32, n int32) int32 {
+	if m == 0 || n == 0 {
+		return 1
+	}
+	r := m % n
+	m = n
+	n = r
+	if r == 0 {
+		return m
+	} else {
+		return GCD(m, n)
+	}
+}
+
+// 返回切片中所有数的累加值
+func Sum(arr []int32) int32 {
+	var sum int32 = 0
+	for _, i := range arr {
+		sum += i
+	}
+	return sum
+}

+ 218 - 0
util/zzt.go

@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package util
+
+import (
+	"bytes"
+	"runtime"
+	"strings"
+	"time"
+	"unicode"
+)
+
+type stringutil struct{}
+
+var StringUtil = &stringutil{}
+
+/*----------------------------------------------------*/
+func (StringUtil *stringutil) LineSeparator() string {
+	var lineSeparator string
+	if strings.Contains(runtime.GOOS, "windos") {
+		lineSeparator = "\r\n"
+	} else if strings.Contains(runtime.GOOS, "mac") {
+		lineSeparator = "\r"
+	} else {
+		lineSeparator = "\n"
+	}
+
+	return lineSeparator
+}
+
+func (StringUtil *stringutil) Equals(str1 string, str2 string) bool {
+	return str1 == str2
+}
+
+func (StringUtil *stringutil) EqualsIgnoreCase(str1 string, str2 string) bool {
+	return strings.ToUpper(str1) == strings.ToUpper(str2)
+}
+
+func (StringUtil *stringutil) StartsWith(s string, subStr string) bool {
+	return strings.Index(s, subStr) == 0
+}
+
+func (StringUtil *stringutil) StartWithIgnoreCase(s string, subStr string) bool {
+	return strings.HasPrefix(strings.ToLower(s), strings.ToLower(subStr))
+}
+
+func (StringUtil *stringutil) EndsWith(s string, subStr string) bool {
+	return strings.LastIndex(s, subStr) == len(s)-1
+}
+
+func (StringUtil *stringutil) IsDigit(str string) bool {
+	if str == "" {
+		return false
+	}
+	sz := len(str)
+	for i := 0; i < sz; i++ {
+		if unicode.IsDigit(rune(str[i])) {
+			continue
+		} else {
+			return false
+		}
+	}
+	return true
+}
+
+func (StringUtil *stringutil) FormatDir(dir string) string {
+	dir = strings.TrimSpace(dir)
+	if dir != "" {
+		if !StringUtil.EndsWith(dir, PathSeparator) {
+			dir += PathSeparator
+		}
+	}
+	return dir
+}
+
+func (StringUtil *stringutil) HexStringToBytes(s string) []byte {
+	str := s
+
+	bs := make([]byte, 0)
+	flag := false
+
+	str = strings.TrimSpace(str)
+	if strings.Index(str, "0x") == 0 || strings.Index(str, "0X") == 0 {
+		str = str[2:]
+	}
+
+	if len(str) == 0 {
+		return bs
+	}
+
+	var bsChr []byte
+	l := len(str)
+
+	if l%2 == 0 {
+		bsChr = []byte(str)
+	} else {
+		l += 1
+		bsChr = make([]byte, l)
+		bsChr[0] = '0'
+		for i := 0; i < l-1; i++ {
+			bsChr[i+1] = str[i]
+		}
+	}
+
+	bs = make([]byte, l/2)
+
+	pos := 0
+	for i := 0; i < len(bsChr); i += 2 {
+		bt := convertHex(bsChr[i])
+		bt2 := convertHex(bsChr[i+1])
+		if int(bt) == 0xff || int(bt2) == 0xff {
+			flag = true
+			break
+		}
+
+		bs[pos] = byte(bt*16 + bt2)
+		pos++
+	}
+
+	if flag {
+		bs = ([]byte)(str)
+	}
+
+	return bs
+}
+
+func convertHex(chr byte) byte {
+	if chr >= '0' && chr <= '9' {
+		return chr - '0'
+	} else if chr >= 'a' && chr <= 'f' {
+		return chr - 'a' + 10
+	} else if chr >= 'A' && chr <= 'F' {
+		return chr - 'A' + 10
+	} else {
+		return 0xff
+	}
+}
+
+func (StringUtil *stringutil) BytesToHexString(bs []byte, pre bool) string {
+	if bs == nil {
+		return ""
+	}
+	if len(bs) == 0 {
+		return ""
+	}
+
+	hexDigits := "0123456789ABCDEF"
+	ret := new(strings.Builder)
+	for _, b := range bs {
+		ret.WriteByte(hexDigits[0x0F&(b>>4)])
+		ret.WriteByte(hexDigits[0x0F&b])
+	}
+	if pre {
+		return "0x" + ret.String()
+	}
+	return ret.String()
+}
+
+func (StringUtil *stringutil) ProcessSingleQuoteOfName(name string) string {
+	return StringUtil.processQuoteOfName(name, "'")
+}
+
+func (StringUtil *stringutil) ProcessDoubleQuoteOfName(name string) string {
+	return StringUtil.processQuoteOfName(name, "\"")
+}
+
+func (StringUtil *stringutil) processQuoteOfName(name string, quote string) string {
+	if quote == "" || name == "" {
+		return name
+	}
+
+	temp := name
+	result := bytes.NewBufferString("")
+	index := -1
+	quetoLength := len(quote)
+	index = strings.Index(temp, quote)
+	for index != -1 {
+		result.WriteString(temp[:index+quetoLength])
+		result.WriteString(quote)
+		temp = temp[index+quetoLength:]
+		index = strings.Index(temp, quote)
+	}
+	result.WriteString(temp)
+	return result.String()
+}
+
+func (StringUtil *stringutil) FormatTime() string {
+	return time.Now().Format("2006-01-02 15:04:05")
+}
+
+func (StringUtil *stringutil) SubstringBetween(str string, open string, close string) string {
+	if str == "" {
+		return ""
+	}
+
+	iopen := -1
+	if open != "" {
+		iopen = strings.Index(str, open)
+	}
+
+	iclose := -1
+	if close != "" {
+		iclose = strings.LastIndex(str, close)
+	}
+
+	if iopen == -1 && iclose == -1 {
+		return ""
+	} else if iopen == -1 {
+		return str[0:iclose]
+	} else if iclose == -1 {
+		return str[iopen:]
+	} else {
+		return str[iopen:iclose]
+	}
+}

+ 142 - 0
v.go

@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package dm
+
+import "database/sql/driver"
+
+type DmStruct struct {
+	TypeData
+	m_strctDesc *StructDescriptor // 结构体的描述信息
+
+	m_attribs []TypeData // 各属性值
+
+	m_objCount int // 一个数组项中存在对象类型的个数(class、动态数组)
+
+	m_strCount int // 一个数组项中存在字符串类型的个数
+
+	typeName string
+
+	elements []interface{}
+
+	// Valid为false代表DmArray数据在数据库中为NULL
+	Valid bool
+}
+
+// 数据库自定义类型Struct构造函数,typeName为库中定义的类型名称,elements为该类型每个字段的值
+//
+// 例如,自定义类型语句为:create or replace type myType as object (a1 int, a2 varchar);
+//
+// 则绑入绑出的go对象为: val := dm.NewDmStruct("myType", []interface{} {123, "abc"})
+func NewDmStruct(typeName string, elements []interface{}) *DmStruct {
+	ds := new(DmStruct)
+	ds.typeName = typeName
+	ds.elements = elements
+	ds.Valid = true
+	return ds
+}
+
+func (ds *DmStruct) create(dc *DmConnection) (*DmStruct, error) {
+	desc, err := newStructDescriptor(ds.typeName, dc)
+	if err != nil {
+		return nil, err
+	}
+	return ds.createByStructDescriptor(desc, dc)
+}
+
+func newDmStructByTypeData(atData []TypeData, desc *TypeDescriptor) *DmStruct {
+	ds := new(DmStruct)
+	ds.Valid = true
+	ds.initTypeData()
+	ds.m_strctDesc = newStructDescriptorByTypeDescriptor(desc)
+	ds.m_attribs = atData
+	return ds
+}
+
+func (dest *DmStruct) Scan(src interface{}) error {
+	if dest == nil {
+		return ECGO_STORE_IN_NIL_POINTER.throw()
+	}
+	switch src := src.(type) {
+	case nil:
+		*dest = *new(DmStruct)
+		// 将Valid标志置false表示数据库中该列为NULL
+		(*dest).Valid = false
+		return nil
+	case *DmStruct:
+		*dest = *src
+		return nil
+	default:
+		return UNSUPPORTED_SCAN.throw()
+	}
+}
+
+func (dt DmStruct) Value() (driver.Value, error) {
+	if !dt.Valid {
+		return nil, nil
+	}
+	return dt, nil
+}
+
+func (ds *DmStruct) getAttribsTypeData() []TypeData {
+	return ds.m_attribs
+}
+
+func (ds *DmStruct) createByStructDescriptor(desc *StructDescriptor, conn *DmConnection) (*DmStruct, error) {
+	ds.initTypeData()
+
+	if nil == desc {
+		return nil, ECGO_INVALID_PARAMETER_VALUE.throw()
+	}
+
+	ds.m_strctDesc = desc
+	if nil == ds.elements {
+		ds.m_attribs = make([]TypeData, desc.getSize())
+	} else {
+		if desc.getSize() != len(ds.elements) && desc.getObjId() != 4 {
+			return nil, ECGO_STRUCT_MEM_NOT_MATCH.throw()
+		}
+		var err error
+		ds.m_attribs, err = TypeDataSV.toStruct(ds.elements, ds.m_strctDesc.m_typeDesc)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return ds, nil
+}
+
+// 获取Struct对象在数据库中的类型名称
+func (ds *DmStruct) GetSQLTypeName() (string, error) {
+	return ds.m_strctDesc.m_typeDesc.getFulName()
+}
+
+// 获取Struct对象中的各个字段的值
+func (ds *DmStruct) GetAttributes() ([]interface{}, error) {
+	return TypeDataSV.toJavaArrayByDmStruct(ds)
+}
+
+func (ds *DmStruct) checkCol(col int) error {
+	if col < 1 || col > len(ds.m_attribs) {
+		return ECGO_INVALID_SEQUENCE_NUMBER.throw()
+	}
+	return nil
+}
+
+// 获取指定索引的成员变量值,以TypeData的形式给出,col 1 based
+func (ds *DmStruct) getAttrValue(col int) (*TypeData, error) {
+	err := ds.checkCol(col)
+	if err != nil {
+		return nil, err
+	}
+	return &ds.m_attribs[col-1], nil
+}
+
+func (ds *DmStruct) checkValid() error {
+	if !ds.Valid {
+		return ECGO_IS_NULL.throw()
+	}
+	return nil
+}

+ 226 - 0
w.go

@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package dm
+
+import (
+	"database/sql/driver"
+	"strings"
+	"time"
+)
+
+const (
+	Seconds_1900_1970 = 2209017600
+
+	OFFSET_YEAR = 0
+
+	OFFSET_MONTH = 1
+
+	OFFSET_DAY = 2
+
+	OFFSET_HOUR = 3
+
+	OFFSET_MINUTE = 4
+
+	OFFSET_SECOND = 5
+
+	OFFSET_NANOSECOND = 6
+
+	OFFSET_TIMEZONE = 7
+
+	DT_LEN = 8
+
+	INVALID_VALUE = int(INT32_MIN)
+
+	NANOSECOND_DIGITS = 9
+
+	NANOSECOND_POW = 1000000000
+)
+
+type DmTimestamp struct {
+	dt                  []int
+	dtype               int
+	scale               int
+	oracleFormatPattern string
+	oracleDateLanguage  int
+
+	// Valid为false代表DmArray数据在数据库中为NULL
+	Valid bool
+}
+
+func newDmTimestampFromDt(dt []int, dtype int, scale int) *DmTimestamp {
+	dmts := new(DmTimestamp)
+	dmts.Valid = true
+	dmts.dt = dt
+	dmts.dtype = dtype
+	dmts.scale = scale
+	return dmts
+}
+
+func newDmTimestampFromBytes(bytes []byte, column column, conn *DmConnection) *DmTimestamp {
+	dmts := new(DmTimestamp)
+	dmts.Valid = true
+	dmts.dt = decode(bytes, column.isBdta, column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
+
+	if isLocalTimeZone(int(column.colType), int(column.scale)) {
+		dmts.scale = getLocalTimeZoneScale(int(column.colType), int(column.scale))
+	} else {
+		dmts.scale = int(column.scale)
+	}
+
+	dmts.dtype = int(column.colType)
+	dmts.scale = int(column.scale)
+	dmts.oracleDateLanguage = int(conn.OracleDateLanguage)
+	switch column.colType {
+	case DATE:
+		dmts.oracleFormatPattern = conn.FormatDate
+	case TIME:
+		dmts.oracleFormatPattern = conn.FormatTime
+	case TIME_TZ:
+		dmts.oracleFormatPattern = conn.FormatTimeTZ
+	case DATETIME, DATETIME2:
+		dmts.oracleFormatPattern = conn.FormatTimestamp
+	case DATETIME_TZ, DATETIME2_TZ:
+		dmts.oracleFormatPattern = conn.FormatTimestampTZ
+	}
+	return dmts
+}
+
+func NewDmTimestampFromString(str string) (*DmTimestamp, error) {
+	dt := make([]int, DT_LEN)
+	dtype, err := toDTFromString(strings.TrimSpace(str), dt)
+	if err != nil {
+		return nil, err
+	}
+
+	if dtype == DATE {
+		return newDmTimestampFromDt(dt, dtype, 0), nil
+	}
+	return newDmTimestampFromDt(dt, dtype, 6), nil
+}
+
+func NewDmTimestampFromTime(time time.Time) *DmTimestamp {
+	dt := toDTFromTime(time)
+	return newDmTimestampFromDt(dt, DATETIME, 6)
+}
+
+func (dmTimestamp *DmTimestamp) ToTime() time.Time {
+	return toTimeFromDT(dmTimestamp.dt, 0)
+}
+
+// 获取年月日时分秒毫秒时区
+func (dmTimestamp *DmTimestamp) GetDt() []int {
+	return dmTimestamp.dt
+}
+
+func (dmTimestamp *DmTimestamp) CompareTo(ts DmTimestamp) int {
+	if dmTimestamp.ToTime().Equal(ts.ToTime()) {
+		return 0
+	} else if dmTimestamp.ToTime().Before(ts.ToTime()) {
+		return -1
+	} else {
+		return 1
+	}
+}
+
+func (dmTimestamp *DmTimestamp) String() string {
+	if dmTimestamp.oracleFormatPattern != "" {
+		return dtToStringByOracleFormat(dmTimestamp.dt, dmTimestamp.oracleFormatPattern, int32(dmTimestamp.scale), dmTimestamp.oracleDateLanguage)
+	}
+	return dtToString(dmTimestamp.dt, dmTimestamp.dtype, dmTimestamp.scale)
+}
+
+func (dest *DmTimestamp) Scan(src interface{}) error {
+	if dest == nil {
+		return ECGO_STORE_IN_NIL_POINTER.throw()
+	}
+	switch src := src.(type) {
+	case nil:
+		*dest = *new(DmTimestamp)
+		// 将Valid标志置false表示数据库中该列为NULL
+		(*dest).Valid = false
+		return nil
+	case *DmTimestamp:
+		*dest = *src
+		return nil
+	case time.Time:
+		ret := NewDmTimestampFromTime(src)
+		*dest = *ret
+		return nil
+	case string:
+		ret, err := NewDmTimestampFromString(src)
+		if err != nil {
+			return err
+		}
+		*dest = *ret
+		return nil
+	default:
+		return UNSUPPORTED_SCAN.throw()
+	}
+}
+
+func (dmTimestamp DmTimestamp) Value() (driver.Value, error) {
+	if !dmTimestamp.Valid {
+		return nil, nil
+	}
+	return dmTimestamp, nil
+}
+
+//func (dmTimestamp *DmTimestamp) toBytes() ([]byte, error) {
+//	return encode(dmTimestamp.dt, dmTimestamp.dtype, dmTimestamp.scale, dmTimestamp.dt[OFFSET_TIMEZONE])
+//}
+
+/**
+ * 获取当前对象的年月日时分秒,如果原来没有decode会先decode;
+ */
+func (dmTimestamp *DmTimestamp) getDt() []int {
+	return dmTimestamp.dt
+}
+
+func (dmTimestamp *DmTimestamp) getTime() int64 {
+	sec := toTimeFromDT(dmTimestamp.dt, 0).Unix()
+	return sec + int64(dmTimestamp.dt[OFFSET_NANOSECOND])
+}
+
+func (dmTimestamp *DmTimestamp) setTime(time int64) {
+	timeInMillis := (time / 1000) * 1000
+	nanos := (int64)((time % 1000) * 1000000)
+	if nanos < 0 {
+		nanos = 1000000000 + nanos
+		timeInMillis = (((time / 1000) - 1) * 1000)
+	}
+	dmTimestamp.dt = toDTFromUnix(timeInMillis, nanos)
+}
+
+func (dmTimestamp *DmTimestamp) setTimezone(tz int) error {
+	// DM中合法的时区取值范围为-12:59至+14:00
+	if tz <= -13*60 || tz > 14*60 {
+		return ECGO_INVALID_DATETIME_FORMAT.throw()
+	}
+	dmTimestamp.dt[OFFSET_TIMEZONE] = tz
+	return nil
+}
+
+func (dmTimestamp *DmTimestamp) getNano() int64 {
+	return int64(dmTimestamp.dt[OFFSET_NANOSECOND] * 1000)
+}
+
+func (dmTimestamp *DmTimestamp) setNano(nano int64) {
+	dmTimestamp.dt[OFFSET_NANOSECOND] = (int)(nano / 1000)
+}
+
+func (dmTimestamp *DmTimestamp) string() string {
+	if dmTimestamp.oracleFormatPattern != "" {
+		return dtToStringByOracleFormat(dmTimestamp.dt, dmTimestamp.oracleFormatPattern, int32(dmTimestamp.scale), dmTimestamp.oracleDateLanguage)
+	}
+	return dtToString(dmTimestamp.dt, dmTimestamp.dtype, dmTimestamp.scale)
+}
+
+func (dmTimestamp *DmTimestamp) checkValid() error {
+	if !dmTimestamp.Valid {
+		return ECGO_IS_NULL.throw()
+	}
+	return nil
+}

+ 192 - 0
x.go

@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package dm
+
+import (
+	"context"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+)
+
+const (
+	STATUS_VALID_TIME = 20 * time.Second // ms
+
+	// sort 值
+	SORT_SERVER_MODE_INVALID = -1 // 不允许连接的模式
+
+	SORT_SERVER_NOT_ALIVE = -2 // 站点无法连接
+
+	SORT_UNKNOWN = INT32_MAX // 站点还未连接过,模式未知
+
+	SORT_NORMAL = 30
+
+	SORT_PRIMARY = 20
+
+	SORT_STANDBY = 10
+
+	// OPEN>MOUNT>SUSPEND
+	SORT_OPEN = 3
+
+	SORT_MOUNT = 2
+
+	SORT_SUSPEND = 1
+)
+
+type ep struct {
+	host            string
+	port            int32
+	alive           bool
+	statusRefreshTs int64 // 状态更新的时间点
+	serverMode      int32
+	serverStatus    int32
+	dscControl      bool
+	sort            int32
+	epSeqno         int32
+	epStatus        int32
+	lock            sync.Mutex
+}
+
+func newEP(host string, port int32) *ep {
+	ep := new(ep)
+	ep.host = host
+	ep.port = port
+	ep.serverMode = -1
+	ep.serverStatus = -1
+	ep.sort = SORT_UNKNOWN
+	return ep
+}
+
+func (ep *ep) getSort(checkTime bool) int32 {
+	if checkTime {
+		if time.Now().UnixNano()-ep.statusRefreshTs < int64(STATUS_VALID_TIME) {
+			return ep.sort
+		} else {
+			return SORT_UNKNOWN
+		}
+	}
+	return ep.sort
+}
+
+func (ep *ep) calcSort(loginMode int32) int32 {
+	var sort int32 = 0
+	switch loginMode {
+	case LOGIN_MODE_PRIMARY_FIRST:
+		{
+			// 主机优先:PRIMARY>NORMAL>STANDBY
+			switch ep.serverMode {
+			case SERVER_MODE_NORMAL:
+				sort += SORT_NORMAL * 10
+			case SERVER_MODE_PRIMARY:
+				sort += SORT_PRIMARY * 100
+			case SERVER_MODE_STANDBY:
+				sort += SORT_STANDBY
+			}
+		}
+	case LOGIN_MODE_STANDBY_FIRST:
+		{
+			// STANDBY优先: STANDBY>PRIMARY>NORMAL
+			switch ep.serverMode {
+			case SERVER_MODE_NORMAL:
+				sort += SORT_NORMAL
+			case SERVER_MODE_PRIMARY:
+				sort += SORT_PRIMARY * 10
+			case SERVER_MODE_STANDBY:
+				sort += SORT_STANDBY * 100
+			}
+		}
+	case LOGIN_MODE_PRIMARY_ONLY:
+		if ep.serverMode != SERVER_MODE_PRIMARY {
+			return SORT_SERVER_MODE_INVALID
+		}
+		sort += SORT_PRIMARY
+	case LOGIN_MODE_STANDBY_ONLY:
+		if ep.serverMode != SERVER_MODE_STANDBY {
+			return SORT_SERVER_MODE_INVALID
+		}
+		sort += SORT_STANDBY
+	}
+
+	switch ep.serverStatus {
+	case SERVER_STATUS_MOUNT:
+		sort += SORT_MOUNT
+	case SERVER_STATUS_OPEN:
+		sort += SORT_OPEN
+	case SERVER_STATUS_SUSPEND:
+		sort += SORT_SUSPEND
+	}
+	return sort
+}
+
+func (ep *ep) refreshStatus(alive bool, conn *DmConnection) {
+	ep.lock.Lock()
+	defer ep.lock.Unlock()
+	ep.alive = alive
+	ep.statusRefreshTs = time.Now().UnixNano()
+	if alive {
+		ep.serverMode = conn.SvrMode
+		ep.serverStatus = conn.SvrStat
+		ep.dscControl = conn.dscControl
+		ep.sort = ep.calcSort(int32(conn.dmConnector.loginMode))
+	} else {
+		ep.serverMode = -1
+		ep.serverStatus = -1
+		ep.dscControl = false
+		ep.sort = SORT_SERVER_NOT_ALIVE
+	}
+}
+
+func (ep *ep) connect(connector *DmConnector) (*DmConnection, error) {
+	connector.host = ep.host
+	connector.port = ep.port
+	conn, err := connector.connectSingle(context.Background())
+	if err != nil {
+		ep.refreshStatus(false, conn)
+		return nil, err
+	}
+	ep.refreshStatus(true, conn)
+	return conn, nil
+}
+
+func (ep *ep) getServerStatusDesc(serverStatus int32) string {
+	ret := ""
+	switch ep.serverStatus {
+	case SERVER_STATUS_OPEN:
+		ret = "OPEN"
+	case SERVER_STATUS_MOUNT:
+		ret = "MOUNT"
+	case SERVER_STATUS_SUSPEND:
+		ret = "SUSPEND"
+	default:
+		ret = "UNKNOWN"
+	}
+	return ret
+}
+
+func (ep *ep) getServerModeDesc(serverMode int32) string {
+	ret := ""
+	switch ep.serverMode {
+	case SERVER_MODE_NORMAL:
+		ret = "NORMAL"
+	case SERVER_MODE_PRIMARY:
+		ret = "PRIMARY"
+	case SERVER_MODE_STANDBY:
+		ret = "STANDBY"
+	default:
+		ret = "UNKNOWN"
+	}
+	return ret
+}
+
+func (ep *ep) String() string {
+	dscControl := ")"
+	if ep.dscControl {
+		dscControl = ", DSC CONTROL)"
+	}
+	return strings.TrimSpace(ep.host) + ":" + strconv.Itoa(int(ep.port)) +
+		" (" + ep.getServerModeDesc(ep.serverMode) + ", " + ep.getServerStatusDesc(ep.serverStatus) + dscControl
+}

+ 148 - 0
y.go

@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package dm
+
+import (
+	"bytes"
+	"math/rand"
+	"sync"
+	"time"
+
+	"gitee.com/chunanyong/dm/util"
+)
+
+/**
+ * dm_svc.conf中配置的服务名对应的一组实例, 以及相关属性和状态信息
+ *
+ * 需求:
+ * 1. 连接均匀分布在各个节点上
+ * 2. loginMode,loginStatus匹配
+ * 3. 连接异常节点比较耗时,在DB列表中包含异常节点时异常连接尽量靠后,减少对建连接速度的影响
+ *
+ *
+ * DB 连接顺序:
+ * 1. well distribution,每次连接都从列表的下一个节点开始
+ * 2. 用DB sort值按从大到小排序,sort为一个四位数XXXX,个位--serverStatus,十位--serverMode,共 有三种模式,最优先的 *100, 次优先的*10
+ */
+type epGroup struct {
+	name       string
+	epList     []*ep
+	props      *Properties
+	epStartPos int32 // wellDistribute 起始位置
+	lock       sync.Mutex
+}
+
+func newEPGroup(name string, serverList []*ep) *epGroup {
+	g := new(epGroup)
+	g.name = name
+	g.epList = serverList
+	if serverList == nil || len(serverList) == 0 {
+		g.epStartPos = -1
+	} else {
+		// 保证进程间均衡,起始位置采用随机值
+		g.epStartPos = rand.Int31n(int32(len(serverList))) - 1
+	}
+	return g
+}
+
+func (g *epGroup) connect(connector *DmConnector) (*DmConnection, error) {
+	var dbSelector = g.getEPSelector(connector)
+	var ex error = nil
+	// 如果配置了loginMode的主、备等优先策略,而未找到最高优先级的节点时持续循环switchtimes次,如果最终还是没有找到最高优先级则选择次优先级的
+	// 如果只有一个节点,一轮即可决定是否连接;多个节点时保证switchTimes轮尝试,最后一轮决定用哪个节点(由于节点已经按照模式优先级排序,最后一轮理论上就是连第一个节点)
+	var cycleCount int32
+	if len(g.epList) == 1 {
+		cycleCount = 1
+	} else {
+		cycleCount = connector.switchTimes + 1
+	}
+	for i := int32(0); i < cycleCount; i++ {
+		// 循环了一遍,如果没有符合要求的, 重新排序, 再尝试连接
+		conn, err := g.traverseServerList(connector, dbSelector, i == 0, i == cycleCount-1)
+		if err != nil {
+			ex = err
+			time.Sleep(time.Duration(connector.switchInterval) * time.Millisecond)
+			continue
+		}
+		return conn, nil
+	}
+	return nil, ex
+}
+
+func (g *epGroup) getEPSelector(connector *DmConnector) *epSelector {
+	if connector.epSelector == TYPE_HEAD_FIRST {
+		return newEPSelector(g.epList)
+	} else {
+		serverCount := int32(len(g.epList))
+		sortEPs := make([]*ep, serverCount)
+		g.lock.Lock()
+		defer g.lock.Unlock()
+		g.epStartPos = (g.epStartPos + 1) % serverCount
+		for i := int32(0); i < serverCount; i++ {
+			sortEPs[i] = g.epList[(i+g.epStartPos)%serverCount]
+		}
+		return newEPSelector(sortEPs)
+	}
+}
+
+/**
+* 从指定编号开始,遍历一遍服务名中的ip列表,只连接指定类型(主机或备机)的ip
+* @param servers
+* @param checkTime
+*
+* @exception
+* DBError.ECJDBC_INVALID_SERVER_MODE 有站点的模式不匹配
+* DBError.ECJDBC_COMMUNITION_ERROR 所有站点都连不上
+ */
+func (g *epGroup) traverseServerList(connector *DmConnector, epSelector *epSelector, first bool, last bool) (*DmConnection, error) {
+	epList := epSelector.sortDBList(first)
+	errorMsg := bytes.NewBufferString("")
+	var ex error = nil // 第一个错误
+	for _, server := range epList {
+		conn, err := server.connect(connector)
+		if err != nil {
+			if ex == nil {
+				ex = err
+			}
+			errorMsg.WriteString("[")
+			errorMsg.WriteString(server.String())
+			errorMsg.WriteString("]")
+			errorMsg.WriteString(err.Error())
+			errorMsg.WriteString(util.StringUtil.LineSeparator())
+			continue
+		}
+		valid, err := epSelector.checkServerMode(conn, last)
+		if err != nil {
+			if ex == nil {
+				ex = err
+			}
+			errorMsg.WriteString("[")
+			errorMsg.WriteString(server.String())
+			errorMsg.WriteString("]")
+			errorMsg.WriteString(err.Error())
+			errorMsg.WriteString(util.StringUtil.LineSeparator())
+			continue
+		}
+		if !valid {
+			conn.close()
+			err = ECGO_INVALID_SERVER_MODE.throw()
+			if ex == nil {
+				ex = err
+			}
+			errorMsg.WriteString("[")
+			errorMsg.WriteString(server.String())
+			errorMsg.WriteString("]")
+			errorMsg.WriteString(err.Error())
+			errorMsg.WriteString(util.StringUtil.LineSeparator())
+			continue
+		}
+		return conn, nil
+	}
+	if ex != nil {
+		return nil, ex
+	}
+	return nil, ECGO_COMMUNITION_ERROR.addDetail(errorMsg.String()).throw()
+}

+ 65 - 0
z.go

@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package dm
+
+import "sort"
+
+const (
+	TYPE_WELL_DISTRIBUTE = 0
+	TYPE_HEAD_FIRST      = 1
+)
+
+type epSelector struct {
+	dbs []*ep
+}
+
+func newEPSelector(dbs []*ep) *epSelector {
+	return &epSelector{dbs}
+}
+
+func (s *epSelector) sortDBList(first bool) []*ep {
+	if !first {
+		// 按sort从大到小排序,相同sort值顺序不变
+		sort.Slice(s.dbs, func(i, j int) bool {
+			return s.dbs[i].getSort(first) > s.dbs[j].getSort(first)
+		})
+	}
+	return s.dbs
+}
+
+func (s *epSelector) checkServerMode(conn *DmConnection, last bool) (bool, error) {
+	// 只连dsc control节点
+	if conn.dmConnector.loginDscCtrl && !conn.dscControl {
+		conn.close()
+		return false, ECGO_INVALID_SERVER_MODE.throw()
+	}
+	// 模式不匹配, 这里使用的是连接之前的sort,连接之后server的状态可能发生改变sort也可能改变
+	if conn.dmConnector.loginStatus > 0 && int(conn.SvrStat) != conn.dmConnector.loginStatus {
+		conn.close()
+		return false, ECGO_INVALID_SERVER_MODE.throw()
+	}
+	if last {
+		switch conn.dmConnector.loginMode {
+		case LOGIN_MODE_PRIMARY_ONLY:
+			return conn.SvrMode == SERVER_MODE_PRIMARY, nil
+		case LOGIN_MODE_STANDBY_ONLY:
+			return conn.SvrMode == SERVER_MODE_STANDBY, nil
+		default:
+			return true, nil
+		}
+	}
+	switch conn.dmConnector.loginMode {
+	case LOGIN_MODE_NORMAL_FIRST:
+		return conn.SvrMode == SERVER_MODE_NORMAL, nil
+	case LOGIN_MODE_PRIMARY_FIRST, LOGIN_MODE_PRIMARY_ONLY:
+		return conn.SvrMode == SERVER_MODE_PRIMARY, nil
+	case LOGIN_MODE_STANDBY_FIRST, LOGIN_MODE_STANDBY_ONLY:
+		return conn.SvrMode == SERVER_MODE_STANDBY, nil
+	default:
+		break
+	}
+	return false, nil
+}

+ 137 - 0
za.go

@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package dm
+
+import (
+	"bytes"
+	"fmt"
+	"runtime"
+
+	"gitee.com/chunanyong/dm/i18n"
+)
+
+// 驱动级错误
+var (
+	DSN_INVALID_SCHEMA             = newDmError(9001, "error.dsn.invalidSchema")
+	UNSUPPORTED_SCAN               = newDmError(9002, "error.unsupported.scan")
+	INVALID_PARAMETER_NUMBER       = newDmError(9003, "error.invalidParameterNumber")
+	THIRD_PART_CIPHER_INIT_FAILED  = newDmError(9004, "error.initThirdPartCipherFailed")
+	ECGO_NOT_QUERY_SQL             = newDmError(9005, "error.notQuerySQL")
+	ECGO_NOT_EXEC_SQL              = newDmError(9006, "error.notExecSQL")
+	ECGO_UNKOWN_NETWORK            = newDmError(9007, "error.unkownNetWork")
+	ECGO_INVALID_CONN              = newDmError(9008, "error.invalidConn")
+	ECGO_UNSUPPORTED_INPARAM_TYPE  = newDmError(9009, "error.unsupportedInparamType")
+	ECGO_UNSUPPORTED_OUTPARAM_TYPE = newDmError(9010, "error.unsupportedOutparamType")
+	ECGO_STORE_IN_NIL_POINTER      = newDmError(9011, "error.storeInNilPointer")
+	ECGO_IS_NULL                   = newDmError(9012, "error.isNull")
+)
+
+var (
+	ECGO_CONNECTION_SWITCH_FAILED    = newDmError(20001, "error.connectionSwitchFailed")
+	ECGO_CONNECTION_SWITCHED         = newDmError(20000, "error.connectionSwitched")
+	ECGO_COMMUNITION_ERROR           = newDmError(6001, "error.communicationError")
+	ECGO_MSG_CHECK_ERROR             = newDmError(6002, "error.msgCheckError")
+	ECGO_INVALID_TIME_INTERVAL       = newDmError(6005, "error.invalidTimeInterval")
+	ECGO_UNSUPPORTED_TYPE            = newDmError(6006, "error.unsupportedType")
+	ECGO_DATA_CONVERTION_ERROR       = newDmError(6007, "error.dataConvertionError")
+	ECGO_INVALID_SQL_TYPE            = newDmError(6009, "error.invalidSqlType")
+	ECGO_INVALID_DATETIME_FORMAT     = newDmError(6015, "error.invalidDateTimeFormat")
+	ECGO_INVALID_COLUMN_TYPE         = newDmError(6016, "error.invalidColumnType")
+	ECGO_RESULTSET_IS_READ_ONLY      = newDmError(6029, "error.resultsetInReadOnlyStatus")
+	ECGO_INVALID_SEQUENCE_NUMBER     = newDmError(6032, "error.invalidSequenceNumber")
+	ECGO_RESULTSET_CLOSED            = newDmError(6034, "errorResultSetColsed")
+	ECGO_STATEMENT_HANDLE_CLOSED     = newDmError(6035, "errorStatementHandleClosed")
+	ECGO_INVALID_PARAMETER_VALUE     = newDmError(6036, "error.invalidParamterValue")
+	ECGO_INVALID_TRAN_ISOLATION      = newDmError(6038, "error.invalidTranIsolation")
+	ECGO_COMMIT_IN_AUTOCOMMIT_MODE   = newDmError(6039, "errorCommitInAutoCommitMode")
+	ECGO_ROLLBACK_IN_AUTOCOMMIT_MODE = newDmError(6040, "errorRollbackInAutoCommitMode")
+	ECGO_UNBINDED_PARAMETER          = newDmError(6054, "error.unbindedParameter")
+	ECGO_PARAM_COUNT_LIMIT           = newDmError(6056, "error.ParamCountLimit")
+	ECGO_INVALID_LENGTH_OR_OFFSET    = newDmError(6057, "error.invalidLenOrOffset")
+	ECGO_INTERVAL_OVERFLOW           = newDmError(6066, "error.intervalValueOverflow")
+	ECGO_STRING_CUT                  = newDmError(6067, "error.stringCut")
+	ECGO_INVALID_HEX                 = newDmError(6068, "error.invalidHex")
+	ECGO_INVALID_CIPHER              = newDmError(6069, "error.invalidCipher")
+	ECGO_INVALID_BFILE_STR           = newDmError(6070, "error.invalidBFile")
+	ECGO_OSAUTH_ERROR                = newDmError(6073, "error.osauthError")
+	ECGO_ERROR_SERVER_VERSION        = newDmError(6074, "error.serverVersion")
+	ECGO_USERNAME_TOO_LONG           = newDmError(6075, "error.usernameTooLong")
+	ECGO_PASSWORD_TOO_LONG           = newDmError(6076, "error.passwordTooLong")
+	ECGO_INVALID_COMPLEX_TYPE_NAME   = newDmError(6079, "error.invalidComplexTypeName")
+	ECGO_STRUCT_MEM_NOT_MATCH        = newDmError(6080, "error.structMemNotMatch")
+	ECGO_INVALID_OBJ_BLOB            = newDmError(6081, "error.invalidObjBlob")
+	ECGO_INVALID_ARRAY_LEN           = newDmError(6082, "error.invalidArrayLen")
+	ECGO_INVALID_SERVER_MODE         = newDmError(6091, "error.invalidServerMode")
+	ECGO_DATA_TOO_LONG               = newDmError(6092, "error.dataTooLong")
+	ECGO_BATCH_ERROR                 = newDmError(6093, "error.batchError")
+	ECGO_MSG_TOO_LONG                = newDmError(6101, "error.msgTooLong")
+	ECGO_INVALID_DATETIME_VALUE      = newDmError(6103, "error.invalidDateTimeValue")
+
+	ECGO_INIT_SSL_FAILED = newDmError(20002, "error.SSLInitFailed")
+	ECGO_LOB_FREED       = newDmError(20003, "error.LobDataHasFreed")
+	ECGO_FATAL_ERROR     = newDmError(20004, "error.fatalError")
+)
+
+// Svr Msg Err
+var (
+	ECGO_DATA_OVERFLOW       = newDmError(-6102, "error.dataOverflow")
+	ECGO_DATETIME_OVERFLOW   = newDmError(-6112, "error.datetimeOverflow")
+	EC_RN_EXCEED_ROWSET_SIZE = newDmError(-7036, "")
+	EC_BP_WITH_ERROR         = newDmError(121, "warning.bpWithErr")
+)
+
+type DmError struct {
+	ErrCode int32
+	ErrText string
+	stack   []uintptr
+	detail  string
+}
+
+func newDmError(errCode int32, errText string) *DmError {
+	de := new(DmError)
+	de.ErrCode = errCode
+	de.ErrText = errText
+	de.stack = nil
+	de.detail = ""
+	return de
+}
+
+func (dmError *DmError) throw() *DmError {
+	var pcs [32]uintptr
+	n := runtime.Callers(2, pcs[:])
+	dmError.stack = pcs[0:n]
+	return dmError
+}
+
+func (dmError *DmError) FormatStack() string {
+	if dmError == nil || dmError.stack == nil {
+		return ""
+	}
+	buffer := bytes.NewBuffer(nil)
+	index := 1
+	space := "  "
+	for _, p := range dmError.stack {
+		if fn := runtime.FuncForPC(p - 1); fn != nil {
+			file, line := fn.FileLine(p - 1)
+			buffer.WriteString(fmt.Sprintf("   %d).%s%s\n    \t%s:%d\n", index, space, fn.Name(), file, line))
+			index++
+		}
+	}
+	return buffer.String()
+}
+
+func (dmError *DmError) Error() string {
+	return fmt.Sprintf("Error %d: %s", dmError.ErrCode, i18n.Get(dmError.ErrText, Locale)) + dmError.detail + "\n" + "stack info:\n" + dmError.FormatStack()
+}
+
+// 扩充ErrText
+func (dmError *DmError) addDetail(detail string) *DmError {
+	dmError.detail = detail
+	return dmError
+}
+func (dmError *DmError) addDetailln(detail string) *DmError {
+	return dmError.addDetail("\n" + detail)
+}

+ 307 - 0
zb.go

@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package dm
+
+const (
+	PARAM_COUNT_LIMIT int32 = 65536
+
+	IGNORE_TARGET_LENGTH int32 = -1
+
+	IGNORE_TARGET_SCALE int32 = -1
+
+	IGNORE_TARGET_TYPE = INT32_MIN
+
+	TYPE_FLAG_UNKNOWN byte = 0 // 未知类型
+
+	TYPE_FLAG_EXACT byte = 1 // 精确类型
+
+	TYPE_FLAG_RECOMMEND byte = 2 // 推荐类型
+
+	IO_TYPE_UNKNOWN int8 = -1
+
+	IO_TYPE_IN int8 = 0
+
+	IO_TYPE_OUT int8 = 1
+
+	IO_TYPE_INOUT int8 = 2
+
+	MASK_ORACLE_DATE int32 = 1
+
+	MASK_ORACLE_FLOAT int32 = 2
+
+	MASK_BFILE int32 = 3
+
+	MASK_LOCAL_DATETIME int32 = 4
+)
+
+type execRetInfo struct {
+	// param
+	outParamDatas [][]byte
+
+	// rs
+	hasResultSet bool
+
+	rsDatas [][][]byte
+
+	rsSizeof int // 结果集数据占用多少空间,(消息中结果集起始位置到 rsCacheOffset
+	// 的空间大小,这和实际的rsDatas占用空间大小有一定出入,这里粗略估算,用于结果集缓存时的空间管理)
+
+	rsCacheOffset int32 // 缓存信息,在响应消息体中的偏移,0表示不存在,仅结果集缓存中可以用
+
+	rsBdta bool
+
+	rsUpdatable bool
+
+	rsRowIds []int64
+
+	// rs cache
+	tbIds []int32
+
+	tbTss []int64
+
+	// print
+	printLen int32
+
+	printMsg string
+
+	// explain
+	explain string
+
+	// 影响行数
+	updateCount int64 // Insert/Update/Delet影响行数, select结果集的总行数
+
+	updateCounts []int64 // 批量影响行数
+
+	// 键
+	rowid int64
+
+	lastInsertId int64
+
+	// other
+	retSqlType int16 // 执行返回的语句类型
+
+	execId int32
+}
+
+type column struct {
+	typeName string
+
+	colType int32
+
+	prec int32
+
+	scale int32
+
+	name string
+
+	tableName string
+
+	schemaName string
+
+	nullable bool
+
+	identity bool
+
+	readonly bool // 是否只读
+
+	baseName string
+
+	// lob info
+	lob bool
+
+	lobTabId int32
+
+	lobColId int16
+
+	// 用于描述ARRAY、STRUCT类型的特有描述信息
+	typeDescriptor *TypeDescriptor
+
+	isBdta bool
+
+	mask int32
+}
+
+type parameter struct {
+	column
+
+	typeFlag byte
+
+	ioType int8
+
+	outJType int32
+
+	outScale int32
+
+	outObjectName string
+
+	cursorStmt *DmStatement
+
+	hasDefault bool
+}
+
+func (column *column) InitColumn() *column {
+	column.typeName = ""
+
+	column.colType = 0
+
+	column.prec = 0
+
+	column.scale = 0
+
+	column.name = ""
+
+	column.tableName = ""
+
+	column.schemaName = ""
+
+	column.nullable = false
+
+	column.identity = false
+
+	column.readonly = false
+
+	column.baseName = ""
+
+	// lob info
+	column.lob = false
+
+	column.lobTabId = 0
+
+	column.lobColId = 0
+
+	// 用于描述ARRAY、STRUCT类型的特有描述信息
+	column.typeDescriptor = nil
+
+	column.isBdta = false
+
+	return column
+}
+
+func (parameter *parameter) InitParameter() *parameter {
+	parameter.InitColumn()
+
+	parameter.typeFlag = TYPE_FLAG_UNKNOWN
+
+	parameter.ioType = IO_TYPE_UNKNOWN
+
+	parameter.outJType = IGNORE_TARGET_TYPE
+
+	parameter.outScale = IGNORE_TARGET_SCALE
+
+	parameter.outObjectName = ""
+
+	parameter.cursorStmt = nil
+
+	return parameter
+}
+
+func (parameter *parameter) resetType(colType int32) {
+	parameter.colType = colType
+	parameter.scale = 0
+	switch colType {
+	case BIT, BOOLEAN:
+		parameter.prec = BIT_PREC
+	case TINYINT:
+		parameter.prec = TINYINT_PREC
+	case SMALLINT:
+		parameter.prec = SMALLINT_PREC
+	case INT:
+		parameter.prec = INT_PREC
+	case BIGINT:
+		parameter.prec = BIGINT_PREC
+	case CHAR, VARCHAR, VARCHAR2:
+		parameter.prec = VARCHAR_PREC
+	case CLOB:
+		parameter.prec = CLOB_PREC
+	case BINARY, VARBINARY:
+		parameter.prec = VARBINARY_PREC
+	case BLOB:
+		parameter.prec = BLOB_PREC
+	case DATE:
+		parameter.prec = DATE_PREC
+	case TIME:
+		parameter.prec = TIME_PREC
+		parameter.scale = 6
+	case TIME_TZ:
+		parameter.prec = TIME_TZ_PREC
+		parameter.scale = 6
+	case DATETIME:
+		parameter.prec = DATETIME_PREC
+		parameter.scale = 6
+	case DATETIME_TZ:
+		parameter.prec = DATETIME_TZ_PREC
+		parameter.scale = 6
+	case DATETIME2:
+		parameter.prec = DATETIME2_PREC
+		parameter.scale = 9
+	case DATETIME2_TZ:
+		parameter.prec = DATETIME2_TZ_PREC
+		parameter.scale = 9
+	case REAL, DOUBLE, DECIMAL, INTERVAL_YM, INTERVAL_DT, ARRAY, CLASS, PLTYPE_RECORD, SARRAY:
+		parameter.prec = 0
+	case UNKNOWN, NULL:
+		// UNKNOWN 导致服务器断言 // setNull导致服务器报错“字符转换失败”
+		parameter.colType = VARCHAR
+		parameter.prec = VARCHAR_PREC
+	default:
+	}
+}
+
+func (execInfo *execRetInfo) union(other *execRetInfo, startRow int, count int) {
+	if count == 1 {
+		execInfo.updateCounts[startRow] = other.updateCount
+	} else if execInfo.updateCounts != nil {
+		copy(execInfo.updateCounts[startRow:startRow+count], other.updateCounts[0:count])
+	}
+	if execInfo.outParamDatas != nil {
+		execInfo.outParamDatas = append(execInfo.outParamDatas, other.outParamDatas...)
+	}
+}
+
+func NewExceInfo() *execRetInfo {
+
+	execInfo := execRetInfo{}
+
+	execInfo.outParamDatas = nil
+
+	execInfo.hasResultSet = false
+
+	execInfo.rsDatas = nil
+
+	execInfo.rsSizeof = 0
+
+	execInfo.rsCacheOffset = 0
+
+	execInfo.rsBdta = false
+
+	execInfo.rsUpdatable = false
+
+	execInfo.rsRowIds = nil
+
+	execInfo.tbIds = nil
+
+	execInfo.tbTss = nil
+
+	execInfo.printLen = 0
+
+	execInfo.printMsg = ""
+
+	execInfo.explain = ""
+
+	execInfo.updateCount = 0
+
+	execInfo.updateCounts = nil
+
+	execInfo.rowid = -1
+
+	execInfo.lastInsertId = 0
+	// other
+	execInfo.retSqlType = -1 // 执行返回的语句类型
+
+	execInfo.execId = 0
+
+	return &execInfo
+}

+ 443 - 0
zc.go

@@ -0,0 +1,443 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"context"
+	"database/sql/driver"
+	"reflect"
+	"sync"
+	"sync/atomic"
+	"time"
+)
+
+type filter interface {
+	DmDriverOpen(filterChain *filterChain, d *DmDriver, dsn string) (*DmConnection, error)
+	DmDriverOpenConnector(filterChain *filterChain, d *DmDriver, dsn string) (*DmConnector, error)
+
+	DmConnectorConnect(filterChain *filterChain, c *DmConnector, ctx context.Context) (*DmConnection, error)
+	DmConnectorDriver(filterChain *filterChain, c *DmConnector) *DmDriver
+
+	DmConnectionBegin(filterChain *filterChain, c *DmConnection) (*DmConnection, error)
+	DmConnectionBeginTx(filterChain *filterChain, c *DmConnection, ctx context.Context, opts driver.TxOptions) (*DmConnection, error)
+	DmConnectionCommit(filterChain *filterChain, c *DmConnection) error
+	DmConnectionRollback(filterChain *filterChain, c *DmConnection) error
+	DmConnectionClose(filterChain *filterChain, c *DmConnection) error
+	DmConnectionPing(filterChain *filterChain, c *DmConnection, ctx context.Context) error
+	DmConnectionExec(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (*DmResult, error)
+	DmConnectionExecContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmResult, error)
+	DmConnectionQuery(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (*DmRows, error)
+	DmConnectionQueryContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmRows, error)
+	DmConnectionPrepare(filterChain *filterChain, c *DmConnection, query string) (*DmStatement, error)
+	DmConnectionPrepareContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string) (*DmStatement, error)
+	DmConnectionResetSession(filterChain *filterChain, c *DmConnection, ctx context.Context) error
+	DmConnectionCheckNamedValue(filterChain *filterChain, c *DmConnection, nv *driver.NamedValue) error
+
+	DmStatementClose(filterChain *filterChain, s *DmStatement) error
+	DmStatementNumInput(filterChain *filterChain, s *DmStatement) int
+	DmStatementExec(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmResult, error)
+	DmStatementExecContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmResult, error)
+	DmStatementQuery(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmRows, error)
+	DmStatementQueryContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmRows, error)
+	DmStatementCheckNamedValue(filterChain *filterChain, s *DmStatement, nv *driver.NamedValue) error
+
+	DmResultLastInsertId(filterChain *filterChain, r *DmResult) (int64, error)
+	DmResultRowsAffected(filterChain *filterChain, r *DmResult) (int64, error)
+
+	DmRowsColumns(filterChain *filterChain, r *DmRows) []string
+	DmRowsClose(filterChain *filterChain, r *DmRows) error
+	DmRowsNext(filterChain *filterChain, r *DmRows, dest []driver.Value) error
+	DmRowsHasNextResultSet(filterChain *filterChain, r *DmRows) bool
+	DmRowsNextResultSet(filterChain *filterChain, r *DmRows) error
+	DmRowsColumnTypeScanType(filterChain *filterChain, r *DmRows, index int) reflect.Type
+	DmRowsColumnTypeDatabaseTypeName(filterChain *filterChain, r *DmRows, index int) string
+	DmRowsColumnTypeLength(filterChain *filterChain, r *DmRows, index int) (length int64, ok bool)
+	DmRowsColumnTypeNullable(filterChain *filterChain, r *DmRows, index int) (nullable, ok bool)
+	DmRowsColumnTypePrecisionScale(filterChain *filterChain, r *DmRows, index int) (precision, scale int64, ok bool)
+}
+
+type IDGenerator int64
+
+var dmDriverIDGenerator = new(IDGenerator)
+var dmConntorIDGenerator = new(IDGenerator)
+var dmConnIDGenerator = new(IDGenerator)
+var dmStmtIDGenerator = new(IDGenerator)
+var dmResultIDGenerator = new(IDGenerator)
+var dmRowsIDGenerator = new(IDGenerator)
+
+func (g *IDGenerator) incrementAndGet() int64 {
+	return atomic.AddInt64((*int64)(g), 1)
+}
+
+type RWSiteEnum int
+
+const (
+	PRIMARY RWSiteEnum = iota
+	STANDBY
+	ANYSITE
+)
+
+var (
+	goMapMu sync.RWMutex
+	goMap   = make(map[string]goRun, 2)
+)
+
+type filterable struct {
+	filterChain *filterChain
+	rwInfo      *rwInfo
+	logInfo     *logInfo
+	recoverInfo *recoverInfo
+	statInfo    *statInfo
+	objId       int64
+	idGenerator *IDGenerator
+}
+
+func runLog() {
+	goMapMu.Lock()
+	_, ok := goMap["log"]
+	if !ok {
+		goMap["log"] = &logWriter{
+			flushQueue: make(chan []byte, LogFlushQueueSize),
+			date:       time.Now().Format("2006-01-02"),
+			logFile:    nil,
+			flushFreq:  LogFlushFreq,
+			filePath:   LogDir,
+			filePrefix: "dm_go",
+			buffer:     Dm_build_287(),
+		}
+		go goMap["log"].doRun()
+	}
+	goMapMu.Unlock()
+}
+
+func runStat() {
+	goMapMu.Lock()
+	_, ok := goMap["stat"]
+	if !ok {
+		goMap["stat"] = newStatFlusher()
+		go goMap["stat"].doRun()
+	}
+	goMapMu.Unlock()
+}
+
+func (f *filterable) createFilterChain(bc *DmConnector, props *Properties) {
+	var filters = make([]filter, 0, 5)
+
+	if bc != nil {
+		if LogLevel != LOG_OFF {
+			filters = append(filters, &logFilter{})
+			f.logInfo = &logInfo{logRecord: new(LogRecord)}
+			runLog()
+		}
+
+		if StatEnable {
+			filters = append(filters, &statFilter{})
+			f.statInfo = newStatInfo()
+			goStatMu.Lock()
+			if goStat == nil {
+				goStat = newGoStat(1000)
+			}
+			goStatMu.Unlock()
+			runStat()
+		}
+
+		if bc.doSwitch != DO_SWITCH_OFF {
+			filters = append(filters, &reconnectFilter{})
+		}
+
+		if bc.rwSeparate {
+			filters = append(filters, &rwFilter{})
+			f.rwInfo = newRwInfo()
+		}
+	} else if props != nil {
+		if ParseLogLevel(props) != LOG_OFF {
+			filters = append(filters, &logFilter{})
+			f.logInfo = &logInfo{logRecord: new(LogRecord)}
+			runLog()
+		}
+
+		if props.GetBool("statEnable", StatEnable) {
+			filters = append(filters, &statFilter{})
+			f.statInfo = newStatInfo()
+			goStatMu.Lock()
+			if goStat == nil {
+				goStat = newGoStat(1000)
+			}
+			goStatMu.Unlock()
+			runStat()
+		}
+
+		if props.GetInt(DoSwitchKey, int(DO_SWITCH_OFF), 0, 2) != int(DO_SWITCH_OFF) {
+			filters = append(filters, &reconnectFilter{})
+			f.recoverInfo = newRecoverInfo()
+		}
+
+		if props.GetBool("rwSeparate", false) {
+			filters = append(filters, &rwFilter{})
+			f.rwInfo = newRwInfo()
+		}
+	}
+
+	f.filterChain = newFilterChain(filters)
+}
+
+func (f *filterable) resetFilterable(src *filterable) {
+	f.filterChain = src.filterChain
+	f.logInfo = src.logInfo
+	f.rwInfo = src.rwInfo
+	f.statInfo = src.statInfo
+}
+
+func (f filterable) getID() int64 {
+	if f.objId < 0 {
+		f.objId = f.idGenerator.incrementAndGet()
+	}
+	return f.objId
+}
+
+type logInfo struct {
+	logRecord            *LogRecord
+	lastExecuteStartNano time.Time
+}
+
+type rwInfo struct {
+	distribute RWSiteEnum
+
+	rwCounter *rwCounter
+
+	connStandby *DmConnection
+
+	connCurrent *DmConnection
+
+	tryRecoverTs int64
+
+	stmtStandby *DmStatement
+
+	stmtCurrent *DmStatement
+
+	readOnly bool
+}
+
+func newRwInfo() *rwInfo {
+	rwInfo := new(rwInfo)
+	rwInfo.distribute = PRIMARY
+	rwInfo.readOnly = true
+	return rwInfo
+}
+
+func (rwi *rwInfo) cleanup() {
+	rwi.distribute = PRIMARY
+	rwi.rwCounter = nil
+	rwi.connStandby = nil
+	rwi.connCurrent = nil
+	rwi.stmtStandby = nil
+	rwi.stmtCurrent = nil
+}
+
+func (rwi *rwInfo) toPrimary() RWSiteEnum {
+	if rwi.distribute != PRIMARY {
+
+		rwi.rwCounter.countPrimary()
+	}
+	rwi.distribute = PRIMARY
+	return rwi.distribute
+}
+
+func (rwi *rwInfo) toAny() RWSiteEnum {
+
+	rwi.distribute = rwi.rwCounter.count(ANYSITE, rwi.connStandby)
+	return rwi.distribute
+}
+
+type recoverInfo struct {
+	checkEpRecoverTs int64
+}
+
+func newRecoverInfo() *recoverInfo {
+	recoverInfo := new(recoverInfo)
+	recoverInfo.checkEpRecoverTs = 0
+	return recoverInfo
+}
+
+type statInfo struct {
+	constructNano int64
+
+	connStat *connectionStat
+
+	lastExecuteStartNano int64
+
+	lastExecuteTimeNano int64
+
+	lastExecuteType ExecuteTypeEnum
+
+	firstResultSet bool
+
+	lastExecuteSql string
+
+	sqlStat *sqlStat
+
+	sql string
+
+	cursorIndex int
+
+	closeCount int
+
+	readStringLength int64
+
+	readBytesLength int64
+
+	openInputStreamCount int
+
+	openReaderCount int
+}
+
+var (
+	goStatMu sync.RWMutex
+	goStat   *GoStat
+)
+
+func newStatInfo() *statInfo {
+	si := new(statInfo)
+	return si
+}
+func (si *statInfo) init(conn *DmConnection) {
+	si.connStat = goStat.createConnStat(conn)
+}
+
+func (si *statInfo) setConstructNano() {
+	si.constructNano = time.Now().UnixNano()
+}
+
+func (si *statInfo) getConstructNano() int64 {
+	return si.constructNano
+}
+
+func (si *statInfo) getConnStat() *connectionStat {
+	return si.connStat
+}
+
+func (si *statInfo) getLastExecuteStartNano() int64 {
+	return si.lastExecuteStartNano
+}
+
+func (si *statInfo) setLastExecuteStartNano(lastExecuteStartNano int64) {
+	si.lastExecuteStartNano = lastExecuteStartNano
+}
+
+func (si *statInfo) getLastExecuteTimeNano() int64 {
+	return si.lastExecuteTimeNano
+}
+
+func (si *statInfo) setLastExecuteTimeNano(lastExecuteTimeNano int64) {
+	si.lastExecuteTimeNano = lastExecuteTimeNano
+}
+
+func (si *statInfo) getLastExecuteType() ExecuteTypeEnum {
+	return si.lastExecuteType
+}
+
+func (si *statInfo) setLastExecuteType(lastExecuteType ExecuteTypeEnum) {
+	si.lastExecuteType = lastExecuteType
+}
+
+func (si *statInfo) isFirstResultSet() bool {
+	return si.firstResultSet
+}
+
+func (si *statInfo) setFirstResultSet(firstResultSet bool) {
+	si.firstResultSet = firstResultSet
+}
+
+func (si *statInfo) getLastExecuteSql() string {
+	return si.lastExecuteSql
+}
+
+func (si *statInfo) setLastExecuteSql(lastExecuteSql string) {
+	si.lastExecuteSql = lastExecuteSql
+}
+
+func (si *statInfo) getSqlStat() *sqlStat {
+	return si.sqlStat
+}
+
+func (si *statInfo) setSqlStat(sqlStat *sqlStat) {
+	si.sqlStat = sqlStat
+}
+
+func (si *statInfo) setConnStat(connStat *connectionStat) {
+	si.connStat = connStat
+}
+
+func (si *statInfo) setConstructNanoWithConstructNano(constructNano int64) {
+	si.constructNano = constructNano
+}
+
+func (si *statInfo) afterExecute(nanoSpan int64) {
+	si.lastExecuteTimeNano = nanoSpan
+}
+
+func (si *statInfo) beforeExecute() {
+	si.lastExecuteStartNano = time.Now().UnixNano()
+}
+
+func (si *statInfo) getSql() string {
+	return si.sql
+}
+
+func (si *statInfo) setSql(sql string) {
+	si.sql = sql
+}
+
+func (si *statInfo) getCursorIndex() int {
+	return si.cursorIndex
+}
+
+func (si *statInfo) setCursorIndex(cursorIndex int) {
+	si.cursorIndex = cursorIndex
+}
+
+func (si *statInfo) getCloseCount() int {
+	return si.closeCount
+}
+
+func (si *statInfo) setCloseCount(closeCount int) {
+	si.closeCount = closeCount
+}
+
+func (si *statInfo) getReadStringLength() int64 {
+	return si.readStringLength
+}
+
+func (si *statInfo) setReadStringLength(readStringLength int64) {
+	si.readStringLength = readStringLength
+}
+
+func (si *statInfo) getReadBytesLength() int64 {
+	return si.readBytesLength
+}
+
+func (si *statInfo) setReadBytesLength(readBytesLength int64) {
+	si.readBytesLength = readBytesLength
+}
+
+func (si *statInfo) getOpenInputStreamCount() int {
+	return si.openInputStreamCount
+}
+
+func (si *statInfo) setOpenInputStreamCount(openInputStreamCount int) {
+	si.openInputStreamCount = openInputStreamCount
+}
+
+func (si *statInfo) getOpenReaderCount() int {
+	return si.openReaderCount
+}
+
+func (si *statInfo) setOpenReaderCount(openReaderCount int) {
+	si.openReaderCount = openReaderCount
+}
+
+func (si *statInfo) incrementCloseCount() {
+	si.closeCount++
+}

+ 403 - 0
zd.go

@@ -0,0 +1,403 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package dm
+
+import (
+	"context"
+	"database/sql/driver"
+	"reflect"
+)
+
+type filterChain struct {
+	filters []filter
+	fpos    int
+}
+
+func newFilterChain(filters []filter) *filterChain {
+	fc := new(filterChain)
+	fc.filters = filters
+	fc.fpos = 0
+	return fc
+}
+
+func (filterChain *filterChain) reset() *filterChain {
+	filterChain.fpos = 0
+	return filterChain
+}
+
+func (filterChain *filterChain) DmDriverOpen(d *DmDriver, dsn string) (*DmConnection, error) {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmDriverOpen(filterChain, d, dsn)
+	}
+
+	return d.open(dsn)
+}
+
+func (filterChain *filterChain) DmDriverOpenConnector(d *DmDriver, dsn string) (*DmConnector, error) {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmDriverOpenConnector(filterChain, d, dsn)
+	}
+
+	return d.openConnector(dsn)
+}
+
+//DmConnector
+func (filterChain *filterChain) DmConnectorConnect(c *DmConnector, ctx context.Context) (*DmConnection, error) {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmConnectorConnect(filterChain, c, ctx)
+	}
+
+	return c.connect(ctx)
+}
+
+func (filterChain *filterChain) DmConnectorDriver(c *DmConnector) *DmDriver {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmConnectorDriver(filterChain, c)
+	}
+
+	return c.driver()
+}
+
+//DmConnection
+func (filterChain *filterChain) DmConnectionBegin(c *DmConnection) (*DmConnection, error) {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmConnectionBegin(filterChain, c)
+	}
+
+	return c.begin()
+}
+func (filterChain *filterChain) DmConnectionBeginTx(c *DmConnection, ctx context.Context, opts driver.TxOptions) (*DmConnection, error) {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmConnectionBeginTx(filterChain, c, ctx, opts)
+	}
+
+	return c.beginTx(ctx, opts)
+}
+
+func (filterChain *filterChain) DmConnectionCommit(c *DmConnection) error {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmConnectionCommit(filterChain, c)
+	}
+
+	return c.commit()
+}
+
+func (filterChain *filterChain) DmConnectionRollback(c *DmConnection) error {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmConnectionRollback(filterChain, c)
+	}
+
+	return c.rollback()
+}
+
+func (filterChain *filterChain) DmConnectionClose(c *DmConnection) error {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmConnectionClose(filterChain, c)
+	}
+
+	return c.close()
+}
+
+func (filterChain *filterChain) DmConnectionPing(c *DmConnection, ctx context.Context) error {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmConnectionPing(filterChain, c, ctx)
+	}
+
+	return c.ping(ctx)
+}
+
+func (filterChain *filterChain) DmConnectionExec(c *DmConnection, query string, args []driver.Value) (*DmResult, error) {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmConnectionExec(filterChain, c, query, args)
+	}
+
+	return c.exec(query, args)
+}
+
+func (filterChain *filterChain) DmConnectionExecContext(c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmResult, error) {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmConnectionExecContext(filterChain, c, ctx, query, args)
+	}
+
+	return c.execContext(ctx, query, args)
+}
+
+func (filterChain *filterChain) DmConnectionQuery(c *DmConnection, query string, args []driver.Value) (*DmRows, error) {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmConnectionQuery(filterChain, c, query, args)
+	}
+
+	return c.query(query, args)
+}
+
+func (filterChain *filterChain) DmConnectionQueryContext(c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmRows, error) {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmConnectionQueryContext(filterChain, c, ctx, query, args)
+	}
+
+	return c.queryContext(ctx, query, args)
+}
+
+func (filterChain *filterChain) DmConnectionPrepare(c *DmConnection, query string) (*DmStatement, error) {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmConnectionPrepare(filterChain, c, query)
+	}
+
+	return c.prepare(query)
+}
+
+func (filterChain *filterChain) DmConnectionPrepareContext(c *DmConnection, ctx context.Context, query string) (*DmStatement, error) {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmConnectionPrepareContext(filterChain, c, ctx, query)
+	}
+
+	return c.prepareContext(ctx, query)
+}
+
+func (filterChain *filterChain) DmConnectionResetSession(c *DmConnection, ctx context.Context) error {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmConnectionResetSession(filterChain, c, ctx)
+	}
+
+	return c.resetSession(ctx)
+}
+
+func (filterChain *filterChain) DmConnectionCheckNamedValue(c *DmConnection, nv *driver.NamedValue) error {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmConnectionCheckNamedValue(filterChain, c, nv)
+	}
+
+	return c.checkNamedValue(nv)
+}
+
+//DmStatement
+func (filterChain *filterChain) DmStatementClose(s *DmStatement) error {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmStatementClose(filterChain, s)
+	}
+
+	return s.close()
+}
+
+func (filterChain *filterChain) DmStatementNumInput(s *DmStatement) int {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmStatementNumInput(filterChain, s)
+	}
+
+	return s.numInput()
+}
+
+func (filterChain *filterChain) DmStatementExec(s *DmStatement, args []driver.Value) (*DmResult, error) {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmStatementExec(filterChain, s, args)
+	}
+
+	return s.exec(args)
+}
+
+func (filterChain *filterChain) DmStatementExecContext(s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmResult, error) {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmStatementExecContext(filterChain, s, ctx, args)
+	}
+
+	return s.execContext(ctx, args)
+}
+
+func (filterChain *filterChain) DmStatementQuery(s *DmStatement, args []driver.Value) (*DmRows, error) {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmStatementQuery(filterChain, s, args)
+	}
+
+	return s.query(args)
+}
+
+func (filterChain *filterChain) DmStatementQueryContext(s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmRows, error) {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmStatementQueryContext(filterChain, s, ctx, args)
+	}
+
+	return s.queryContext(ctx, args)
+}
+
+func (filterChain *filterChain) DmStatementCheckNamedValue(s *DmStatement, nv *driver.NamedValue) error {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmStatementCheckNamedValue(filterChain, s, nv)
+	}
+
+	return s.checkNamedValue(nv)
+}
+
+//DmResult
+func (filterChain *filterChain) DmResultLastInsertId(r *DmResult) (int64, error) {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmResultLastInsertId(filterChain, r)
+	}
+
+	return r.lastInsertId()
+}
+
+func (filterChain *filterChain) DmResultRowsAffected(r *DmResult) (int64, error) {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmResultRowsAffected(filterChain, r)
+	}
+
+	return r.rowsAffected()
+}
+
+//DmRows
+func (filterChain *filterChain) DmRowsColumns(r *DmRows) []string {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmRowsColumns(filterChain, r)
+	}
+
+	return r.columns()
+}
+
+func (filterChain *filterChain) DmRowsClose(r *DmRows) error {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmRowsClose(filterChain, r)
+	}
+
+	return r.close()
+}
+
+func (filterChain *filterChain) DmRowsNext(r *DmRows, dest []driver.Value) error {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmRowsNext(filterChain, r, dest)
+	}
+
+	return r.next(dest)
+}
+
+func (filterChain *filterChain) DmRowsHasNextResultSet(r *DmRows) bool {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmRowsHasNextResultSet(filterChain, r)
+	}
+
+	return r.hasNextResultSet()
+}
+
+func (filterChain *filterChain) DmRowsNextResultSet(r *DmRows) error {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmRowsNextResultSet(filterChain, r)
+	}
+
+	return r.nextResultSet()
+}
+
+func (filterChain *filterChain) DmRowsColumnTypeScanType(r *DmRows, index int) reflect.Type {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmRowsColumnTypeScanType(filterChain, r, index)
+	}
+
+	return r.columnTypeScanType(index)
+}
+
+func (filterChain *filterChain) DmRowsColumnTypeDatabaseTypeName(r *DmRows, index int) string {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmRowsColumnTypeDatabaseTypeName(filterChain, r, index)
+	}
+
+	return r.columnTypeDatabaseTypeName(index)
+}
+
+func (filterChain *filterChain) DmRowsColumnTypeLength(r *DmRows, index int) (length int64, ok bool) {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmRowsColumnTypeLength(filterChain, r, index)
+	}
+
+	return r.columnTypeLength(index)
+}
+
+func (filterChain *filterChain) DmRowsColumnTypeNullable(r *DmRows, index int) (nullable, ok bool) {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmRowsColumnTypeNullable(filterChain, r, index)
+	}
+
+	return r.columnTypeNullable(index)
+}
+
+func (filterChain *filterChain) DmRowsColumnTypePrecisionScale(r *DmRows, index int) (precision, scale int64, ok bool) {
+	if filterChain.fpos < len(filterChain.filters) {
+		f := filterChain.filters[filterChain.fpos]
+		filterChain.fpos++
+		return f.DmRowsColumnTypePrecisionScale(filterChain, r, index)
+	}
+
+	return r.columnTypePrecisionScale(index)
+}

+ 871 - 0
ze.go

@@ -0,0 +1,871 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package dm
+
+import (
+	"context"
+	"database/sql/driver"
+	"reflect"
+	"strconv"
+	"time"
+
+	"gitee.com/chunanyong/dm/util"
+)
+
+type logFilter struct{}
+
+func (filter *logFilter) DmDriverOpen(filterChain *filterChain, d *DmDriver, dsn string) (ret *DmConnection, err error) {
+	var logRecord = d.logInfo.logRecord
+	logRecord.Set(d, "open", dsn)
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	ret, err = filterChain.DmDriverOpen(d, dsn)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	logRecord.SetReturnValue(ret)
+	return
+}
+
+func (filter *logFilter) DmDriverOpenConnector(filterChain *filterChain, d *DmDriver, dsn string) (ret *DmConnector, err error) {
+	var logRecord = d.logInfo.logRecord
+	logRecord.Set(d, "openConnector", dsn)
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	ret, err = filterChain.DmDriverOpenConnector(d, dsn)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	logRecord.SetReturnValue(ret)
+	return
+}
+
+func (filter *logFilter) DmConnectorConnect(filterChain *filterChain, c *DmConnector, ctx context.Context) (ret *DmConnection, err error) {
+	var logRecord = c.logInfo.logRecord
+	logRecord.Set(c, "connect")
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	ret, err = filterChain.DmConnectorConnect(c, ctx)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	logRecord.SetReturnValue(ret)
+	return
+}
+
+func (filter *logFilter) DmConnectorDriver(filterChain *filterChain, c *DmConnector) (ret *DmDriver) {
+	var logRecord = c.logInfo.logRecord
+	logRecord.Set(c, "driver")
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	ret = filterChain.DmConnectorDriver(c)
+	logRecord.SetReturnValue(ret)
+	return
+}
+
+func (filter *logFilter) DmConnectionBegin(filterChain *filterChain, c *DmConnection) (ret *DmConnection, err error) {
+	var logRecord = c.logInfo.logRecord
+	logRecord.Set(c, "begin")
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	ret, err = filterChain.DmConnectionBegin(c)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	logRecord.SetReturnValue(ret)
+	return
+}
+
+func (filter *logFilter) DmConnectionBeginTx(filterChain *filterChain, c *DmConnection, ctx context.Context, opts driver.TxOptions) (ret *DmConnection, err error) {
+	var logRecord = c.logInfo.logRecord
+	logRecord.Set(c, "beginTx", opts)
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	ret, err = filterChain.DmConnectionBeginTx(c, ctx, opts)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	logRecord.SetReturnValue(ret)
+	return
+}
+
+func (filter *logFilter) DmConnectionCommit(filterChain *filterChain, c *DmConnection) (err error) {
+	var logRecord = c.logInfo.logRecord
+	logRecord.Set(c, "commit")
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	err = filterChain.DmConnectionCommit(c)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	return
+}
+
+func (filter *logFilter) DmConnectionRollback(filterChain *filterChain, c *DmConnection) (err error) {
+	var logRecord = c.logInfo.logRecord
+	logRecord.Set(c, "rollback")
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	err = filterChain.DmConnectionRollback(c)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	return
+}
+
+func (filter *logFilter) DmConnectionClose(filterChain *filterChain, c *DmConnection) (err error) {
+	var logRecord = c.logInfo.logRecord
+	logRecord.Set(c, "close")
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	err = filterChain.DmConnectionClose(c)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	return
+}
+
+func (filter *logFilter) DmConnectionPing(filterChain *filterChain, c *DmConnection, ctx context.Context) (err error) {
+	var logRecord = c.logInfo.logRecord
+	logRecord.Set(c, "ping")
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	err = filterChain.DmConnectionPing(c, ctx)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	return
+}
+
+func (filter *logFilter) DmConnectionExec(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (ret *DmResult, err error) {
+	var logRecord = c.logInfo.logRecord
+	logRecord.Set(c, "executeByStmt", query, args)
+	defer func() {
+		filter.executeAfter(c.logInfo, logRecord)
+		filter.doLog(logRecord)
+	}()
+	logRecord.SetSql(query)
+	filter.executeBefore(c.logInfo)
+	ret, err = filterChain.DmConnectionExec(c, query, args)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	logRecord.SetReturnValue(ret)
+	return
+}
+
+func (filter *logFilter) DmConnectionExecContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (ret *DmResult, err error) {
+	var logRecord = c.logInfo.logRecord
+	logRecord.Set(c, "executeCtx", query, args)
+	defer func() {
+		filter.executeAfter(c.logInfo, logRecord)
+		filter.doLog(logRecord)
+	}()
+	logRecord.SetSql(query)
+	filter.executeBefore(c.logInfo)
+	ret, err = filterChain.DmConnectionExecContext(c, ctx, query, args)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	logRecord.SetReturnValue(ret)
+	return
+}
+
+func (filter *logFilter) DmConnectionQuery(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (ret *DmRows, err error) {
+	var logRecord = c.logInfo.logRecord
+	logRecord.Set(c, "query", query, args)
+	defer func() {
+		filter.executeAfter(c.logInfo, logRecord)
+		filter.doLog(logRecord)
+	}()
+	logRecord.SetSql(query)
+	filter.executeBefore(c.logInfo)
+	ret, err = filterChain.DmConnectionQuery(c, query, args)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	logRecord.SetReturnValue(ret)
+	return
+}
+
+func (filter *logFilter) DmConnectionQueryContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (ret *DmRows, err error) {
+	var logRecord = c.logInfo.logRecord
+	logRecord.Set(c, "queryCtx", query, args)
+	defer func() {
+		filter.executeAfter(c.logInfo, logRecord)
+		filter.doLog(logRecord)
+	}()
+	logRecord.SetSql(query)
+	filter.executeBefore(c.logInfo)
+	ret, err = filterChain.DmConnectionQueryContext(c, ctx, query, args)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	logRecord.SetReturnValue(ret)
+	return
+}
+
+func (filter *logFilter) DmConnectionPrepare(filterChain *filterChain, c *DmConnection, query string) (ret *DmStatement, err error) {
+	var logRecord = c.logInfo.logRecord
+	logRecord.Set(c, "prepareStatement", query)
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	logRecord.SetSql(query)
+	ret, err = filterChain.DmConnectionPrepare(c, query)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	logRecord.SetReturnValue(ret)
+	return
+}
+
+func (filter *logFilter) DmConnectionPrepareContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string) (ret *DmStatement, err error) {
+	var logRecord = c.logInfo.logRecord
+	logRecord.Set(c, "prepareStatementCtx", query)
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	logRecord.SetSql(query)
+	ret, err = filterChain.DmConnectionPrepareContext(c, ctx, query)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	logRecord.SetReturnValue(ret)
+	return
+}
+
+func (filter *logFilter) DmConnectionResetSession(filterChain *filterChain, c *DmConnection, ctx context.Context) (err error) {
+	var logRecord = c.logInfo.logRecord
+	logRecord.Set(c, "resetSession")
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	err = filterChain.DmConnectionResetSession(c, ctx)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	return
+}
+
+func (filter *logFilter) DmConnectionCheckNamedValue(filterChain *filterChain, c *DmConnection, nv *driver.NamedValue) (err error) {
+	var logRecord = c.logInfo.logRecord
+	logRecord.Set(c, "checkNamedValue", nv)
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	err = filterChain.DmConnectionCheckNamedValue(c, nv)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	return
+}
+
+func (filter *logFilter) DmStatementClose(filterChain *filterChain, s *DmStatement) (err error) {
+	var logRecord = s.logInfo.logRecord
+	logRecord.Set(s, "close")
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	err = filterChain.DmStatementClose(s)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	return
+}
+
+func (filter *logFilter) DmStatementNumInput(filterChain *filterChain, s *DmStatement) (ret int) {
+	var logRecord = s.logInfo.logRecord
+	logRecord.Set(s, "numInput")
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	ret = filterChain.DmStatementNumInput(s)
+	logRecord.SetReturnValue(ret)
+	return
+}
+
+func (filter *logFilter) DmStatementExec(filterChain *filterChain, s *DmStatement, args []driver.Value) (ret *DmResult, err error) {
+	var logRecord = s.logInfo.logRecord
+	logRecord.Set(s, "executeByStmt", args)
+	defer func() {
+		filter.executeAfter(s.logInfo, logRecord)
+		filter.doLog(logRecord)
+	}()
+	logRecord.SetSql(s.nativeSql)
+	filter.executeBefore(s.logInfo)
+	ret, err = filterChain.DmStatementExec(s, args)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	logRecord.SetReturnValue(ret)
+	return
+}
+
+func (filter *logFilter) DmStatementExecContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (ret *DmResult, err error) {
+	var logRecord = s.logInfo.logRecord
+	logRecord.Set(s, "executeCtx", args)
+	defer func() {
+		filter.executeAfter(s.logInfo, logRecord)
+		filter.doLog(logRecord)
+	}()
+	logRecord.SetSql(s.nativeSql)
+	filter.executeBefore(s.logInfo)
+	ret, err = filterChain.DmStatementExecContext(s, ctx, args)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	logRecord.SetReturnValue(ret)
+	return
+}
+
+func (filter *logFilter) DmStatementQuery(filterChain *filterChain, s *DmStatement, args []driver.Value) (ret *DmRows, err error) {
+	var logRecord = s.logInfo.logRecord
+	logRecord.Set(s, "query", args)
+	defer func() {
+		filter.executeAfter(s.logInfo, logRecord)
+		filter.doLog(logRecord)
+	}()
+	logRecord.SetSql(s.nativeSql)
+	filter.executeBefore(s.logInfo)
+	ret, err = filterChain.DmStatementQuery(s, args)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	logRecord.SetReturnValue(ret)
+	return
+}
+
+func (filter *logFilter) DmStatementQueryContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (ret *DmRows, err error) {
+	var logRecord = s.logInfo.logRecord
+	logRecord.Set(s, "queryCtx", args)
+	defer func() {
+		filter.executeAfter(s.logInfo, logRecord)
+		filter.doLog(logRecord)
+	}()
+	logRecord.SetSql(s.nativeSql)
+	filter.executeBefore(s.logInfo)
+	ret, err = filterChain.DmStatementQueryContext(s, ctx, args)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	logRecord.SetReturnValue(ret)
+	return
+}
+
+func (filter *logFilter) DmStatementCheckNamedValue(filterChain *filterChain, s *DmStatement, nv *driver.NamedValue) (err error) {
+	var logRecord = s.logInfo.logRecord
+	logRecord.Set(s, "checkNamedValue", nv)
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	err = filterChain.DmStatementCheckNamedValue(s, nv)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	return
+}
+
+func (filter *logFilter) DmResultLastInsertId(filterChain *filterChain, r *DmResult) (ret int64, err error) {
+	var logRecord = r.logInfo.logRecord
+	logRecord.Set(r, "lastInsertId")
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	ret, err = filterChain.DmResultLastInsertId(r)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	logRecord.SetReturnValue(ret)
+	return
+}
+
+func (filter *logFilter) DmResultRowsAffected(filterChain *filterChain, r *DmResult) (ret int64, err error) {
+	var logRecord = r.logInfo.logRecord
+	logRecord.Set(r, "rowsAffected")
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	ret, err = filterChain.DmResultRowsAffected(r)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	logRecord.SetReturnValue(ret)
+	return
+}
+
+func (filter *logFilter) DmRowsColumns(filterChain *filterChain, r *DmRows) (ret []string) {
+	var logRecord = r.logInfo.logRecord
+	logRecord.Set(r, "columns")
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	ret = filterChain.DmRowsColumns(r)
+	logRecord.SetReturnValue(ret)
+	return
+}
+
+func (filter *logFilter) DmRowsClose(filterChain *filterChain, r *DmRows) (err error) {
+	var logRecord = r.logInfo.logRecord
+	logRecord.Set(r, "close")
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	err = filterChain.DmRowsClose(r)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	return
+}
+
+func (filter *logFilter) DmRowsNext(filterChain *filterChain, r *DmRows, dest []driver.Value) (err error) {
+	var logRecord = r.logInfo.logRecord
+	logRecord.Set(r, "next", dest)
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	err = filterChain.DmRowsNext(r, dest)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	return
+}
+
+func (filter *logFilter) DmRowsHasNextResultSet(filterChain *filterChain, r *DmRows) (ret bool) {
+	var logRecord = r.logInfo.logRecord
+	logRecord.Set(r, "hasNextResultSet")
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	ret = filterChain.DmRowsHasNextResultSet(r)
+	logRecord.SetReturnValue(ret)
+	return
+}
+
+func (filter *logFilter) DmRowsNextResultSet(filterChain *filterChain, r *DmRows) (err error) {
+	var logRecord = r.logInfo.logRecord
+	logRecord.Set(r, "nextResultSet")
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	err = filterChain.DmRowsNextResultSet(r)
+	if err != nil {
+		logRecord.SetError(err)
+		return
+	}
+	return
+}
+
+func (filter *logFilter) DmRowsColumnTypeScanType(filterChain *filterChain, r *DmRows, index int) (ret reflect.Type) {
+	var logRecord = r.logInfo.logRecord
+	logRecord.Set(r, "columnTypeScanType", index)
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	ret = filterChain.DmRowsColumnTypeScanType(r, index)
+	logRecord.SetReturnValue(ret)
+	return
+}
+
+func (filter *logFilter) DmRowsColumnTypeDatabaseTypeName(filterChain *filterChain, r *DmRows, index int) (ret string) {
+	var logRecord = r.logInfo.logRecord
+	logRecord.Set(r, "columnTypeDatabaseTypeName", index)
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	ret = filterChain.DmRowsColumnTypeDatabaseTypeName(r, index)
+	logRecord.SetReturnValue(ret)
+	return
+}
+
+func (filter *logFilter) DmRowsColumnTypeLength(filterChain *filterChain, r *DmRows, index int) (length int64, ok bool) {
+	var logRecord = r.logInfo.logRecord
+	logRecord.Set(r, "columnTypeLength", index)
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	length, ok = filterChain.DmRowsColumnTypeLength(r, index)
+	if ok {
+		logRecord.SetReturnValue(length)
+	} else {
+		logRecord.SetReturnValue(-1)
+	}
+	return
+}
+
+func (filter *logFilter) DmRowsColumnTypeNullable(filterChain *filterChain, r *DmRows, index int) (nullable, ok bool) {
+	var logRecord = r.logInfo.logRecord
+	logRecord.Set(r, "columnTypeNullable", index)
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	nullable, ok = filterChain.DmRowsColumnTypeNullable(r, index)
+	if ok {
+		logRecord.SetReturnValue(nullable)
+	} else {
+		logRecord.SetReturnValue(false)
+	}
+	return
+}
+
+func (filter *logFilter) DmRowsColumnTypePrecisionScale(filterChain *filterChain, r *DmRows, index int) (precision, scale int64, ok bool) {
+	var logRecord = r.logInfo.logRecord
+	logRecord.Set(r, "columnTypePrecisionScale", index)
+	defer func() {
+		filter.doLog(logRecord)
+	}()
+	precision, scale, ok = filterChain.DmRowsColumnTypePrecisionScale(r, index)
+	if ok {
+		logRecord.SetReturnValue(strconv.FormatInt(precision, 10) + "&" + strconv.FormatInt(scale, 10))
+	} else {
+		logRecord.SetReturnValue("-1&-1")
+	}
+	return
+}
+
+func (filter *logFilter) executeBefore(logInfo *logInfo) {
+	if LogFilterLogger.IsSqlEnabled() {
+		logInfo.lastExecuteStartNano = time.Now()
+	}
+}
+
+func (filter *logFilter) executeAfter(logInfo *logInfo, record *LogRecord) {
+	if LogFilterLogger.IsSqlEnabled() {
+		record.SetUsedTime(time.Since(logInfo.lastExecuteStartNano))
+	}
+}
+
+func (filter *logFilter) doLog(record *LogRecord) {
+
+	if record == nil {
+		return
+	}
+	if record.GetError() != nil {
+		LogFilterLogger.ErrorWithErr(record.ToString(), record.GetError())
+	} else if record.GetSql() != "" && LogFilterLogger.IsSqlEnabled() {
+		LogFilterLogger.Sql(record.ToString())
+	} else {
+		LogFilterLogger.Info(record.ToString())
+	}
+}
+
+/************************************************************************************************************/
+type Logger struct {
+}
+
+var LogFilterLogger = &Logger{}
+var ConnLogger = &Logger{}
+var AccessLogger = &Logger{}
+
+func (logger Logger) IsDebugEnabled() bool {
+	return LogLevel >= LOG_DEBUG
+}
+func (logger Logger) IsErrorEnabled() bool {
+	return LogLevel >= LOG_ERROR
+}
+func (logger Logger) IsInfoEnabled() bool {
+	return LogLevel >= LOG_INFO
+}
+func (logger Logger) IsWarnEnabled() bool {
+	return LogLevel >= LOG_WARN
+}
+func (logger Logger) IsSqlEnabled() bool {
+	return LogLevel >= LOG_SQL
+}
+func (logger Logger) Debug(msg string) {
+	if logger.IsDebugEnabled() {
+		logger.println(logger.formatHead("DEBUG") + msg)
+	}
+}
+func (logger Logger) DebugWithErr(msg string, err error) {
+	if logger.IsDebugEnabled() {
+		if e, ok := err.(*DmError); ok {
+			logger.println(logger.formatHead("DEBUG") + msg + util.LINE_SEPARATOR + e.FormatStack())
+		} else {
+			logger.println(logger.formatHead("DEBUG") + msg + util.LINE_SEPARATOR + err.Error())
+		}
+	}
+}
+func (logger Logger) Info(msg string) {
+	if logger.IsInfoEnabled() {
+		logger.println(logger.formatHead("INFO ") + msg)
+	}
+}
+func (logger Logger) Sql(msg string) {
+	if logger.IsSqlEnabled() {
+		logger.println(logger.formatHead("SQL  ") + msg)
+	}
+}
+func (logger Logger) Warn(msg string) {
+	if logger.IsWarnEnabled() {
+		logger.println(logger.formatHead("WARN ") + msg)
+	}
+}
+func (logger Logger) ErrorWithErr(msg string, err error) {
+	if e, ok := err.(*DmError); ok {
+		logger.println(logger.formatHead("ERROR") + msg + util.LINE_SEPARATOR + e.FormatStack())
+	} else {
+		logger.println(logger.formatHead("ERROR") + msg + util.LINE_SEPARATOR + err.Error())
+	}
+}
+
+// TODO: 获取goroutine objId
+func (logger Logger) formatHead(head string) string {
+	// return "[" + head + " - " + StringUtil.formatTime() + "] tid:" + Thread.currentThread().getId();
+	return "[" + head + " - " + util.StringUtil.FormatTime() + "]"
+}
+func (logger Logger) println(msg string) {
+	goMap["log"].(*logWriter).WriteLine(msg)
+}
+
+/*************************************************************************************************/
+func formatSource(source interface{}) string {
+	if source == nil {
+		return ""
+	}
+	var str string
+	switch src := source.(type) {
+	case string:
+		str += src
+	case *DmDriver:
+		str += formatDriver(src)
+	case *DmConnector:
+		str += formatContor(src)
+	case *DmConnection:
+		str += formatConn(src)
+	case *DmStatement:
+		str += formatConn(src.dmConn) + ", "
+		str += formatStmt(src)
+	case *DmResult:
+		str += formatConn(src.dmStmt.dmConn) + ", "
+		str += formatStmt(src.dmStmt) + ", "
+		str += formatRs(src)
+	case *DmRows:
+		str += formatConn(src.CurrentRows.dmStmt.dmConn) + ", "
+		str += formatStmt(src.CurrentRows.dmStmt) + ", "
+		str += formatRows(src)
+	default:
+		str += reflect.TypeOf(src).String() + "@" + reflect.ValueOf(src).Addr().String()
+	}
+	return str
+}
+
+func formatDriver(driver *DmDriver) string {
+	if driver != nil && driver.logInfo != nil {
+		return "driver-" + strconv.FormatInt(driver.getID(), 10)
+	}
+	return "driver-nil"
+}
+
+func formatContor(contor *DmConnector) string {
+	if contor != nil && contor.logInfo != nil {
+		return "contor-" + strconv.FormatInt(contor.getID(), 10)
+	}
+	return "contor-nil"
+}
+
+func formatConn(conn *DmConnection) string {
+	if conn != nil && conn.logInfo != nil {
+		return "conn-" + strconv.FormatInt(conn.getID(), 10)
+	}
+	return "conn-nil"
+}
+
+func formatStmt(stmt *DmStatement) string {
+	if stmt != nil && stmt.logInfo != nil {
+		return "stmt-" + strconv.FormatInt(stmt.getID(), 10)
+	}
+	return "stmt-nil"
+}
+
+func formatRs(result *DmResult) string {
+	if result != nil && result.logInfo != nil {
+		return "rs-" + strconv.FormatInt(result.getID(), 10)
+	}
+	return "rs-nil"
+}
+
+func formatRows(rows *DmRows) string {
+	if rows != nil && rows.logInfo != nil {
+		return "rows-" + strconv.FormatInt(rows.getID(), 10)
+	}
+	return "rows-nil"
+}
+
+func formatTrace(source string, method string, returnValue interface{}, params ...interface{}) string {
+	var str string
+	if source != "" {
+		str += "{ " + source + " } "
+	}
+	str += method + "("
+	var paramStartIndex = 0
+	if params != nil && len(params) > paramStartIndex {
+		for i := paramStartIndex; i < len(params); i++ {
+			if i != paramStartIndex {
+				str += ", "
+			}
+			if params[i] != nil {
+				str += reflect.TypeOf(params[i]).String()
+			} else {
+				str += "nil"
+			}
+		}
+	}
+	str += ")"
+	if returnValue != nil {
+		str += ": " + formatReturn(returnValue)
+	}
+	str += ";  "
+	if params != nil && len(params) > paramStartIndex {
+		str += "[PARAMS]: "
+		for i := paramStartIndex; i < len(params); i++ {
+			if i != 0 {
+				str += ", "
+			}
+			if s, ok := params[i].(string); ok {
+				str += "\"" + s + "\""
+			} else {
+				str += reflect.ValueOf(params[i]).String()
+			}
+		}
+		str += "; "
+	}
+	return str
+}
+
+func formatReturn(returnObj interface{}) string {
+	var str string
+	switch o := returnObj.(type) {
+	case *DmConnection:
+		str = formatConn(o)
+		sessID := o.SessionID
+		if sessID != -1 {
+			str += ", sessionID-0x" + strconv.FormatInt(sessID, 16)
+		}
+	case *DmStatement:
+		str = formatStmt(o)
+		str += ", handle-" + strconv.Itoa(int(o.id))
+	case *DmResult:
+		str = formatRs(o)
+	case *DmRows:
+		str = formatRows(o)
+	case string:
+		str = `"` + o + `"`
+	case nullData:
+		str = "nil"
+	default:
+		str = "unknown"
+	}
+	return str
+}
+
+func formatUsedTime(duration time.Duration) string {
+	return "[USED TIME]: " + duration.String()
+}
+
+/************************************************************************************************************/
+
+type nullData struct{}
+
+var null = nullData{}
+
+type LogRecord struct {
+	source      string
+	method      string
+	params      []interface{}
+	returnValue interface{}
+	e           error
+	usedTime    time.Duration
+	sql         string
+}
+
+func (record *LogRecord) Set(source interface{}, method string, params ...interface{}) {
+	record.source = formatSource(source)
+	record.method = method
+	record.params = params
+}
+
+func (record *LogRecord) SetReturnValue(retValue interface{}) {
+	if retValue == nil {
+		record.returnValue = null
+	} else {
+		record.returnValue = retValue
+	}
+}
+
+func (record *LogRecord) GetReturnValue() interface{} {
+	return record.returnValue
+}
+
+func (record *LogRecord) SetSql(sql string) {
+	record.sql = sql
+}
+
+func (record *LogRecord) GetSql() string {
+	return record.sql
+}
+
+func (record *LogRecord) SetUsedTime(usedTime time.Duration) {
+	record.usedTime = usedTime
+}
+
+func (record *LogRecord) GetUsedTime() time.Duration {
+	return record.usedTime
+}
+
+func (record *LogRecord) SetError(err error) {
+	record.e = err
+}
+
+func (record *LogRecord) GetError() error {
+	return record.e
+}
+
+func (record *LogRecord) ToString() string {
+	var str string
+	str += formatTrace(record.source, record.method, record.returnValue, record.params...)
+	if record.usedTime > 0 {
+		str += formatUsedTime(record.usedTime)
+	}
+	return str
+}

+ 497 - 0
zf.go

@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package dm
+
+import (
+	"context"
+	"database/sql/driver"
+	"io"
+	"reflect"
+	"time"
+
+	"gitee.com/chunanyong/dm/util"
+)
+
+const SQL_GET_DSC_EP_SITE = "SELECT " +
+	"dsc.ep_seqno, " +
+	"(CASE mal.MAL_INST_HOST WHEN '' THEN mal.MAL_HOST ELSE mal.MAL_INST_HOST END) as ep_host, " +
+	"dcr.EP_PORT, " +
+	"dsc.EP_STATUS " +
+	"FROM V$DSC_EP_INFO dsc " +
+	"LEFT join V$DM_MAL_INI mal " +
+	"on dsc.EP_NAME = mal.MAL_INST_NAME " +
+	"LEFT join (SELECT grp.GROUP_TYPE GROUP_TYPE, ep.* FROM SYS.\"V$DCR_GROUP\" grp, SYS.\"V$DCR_EP\" ep where grp.GROUP_NAME = ep.GROUP_NAME) dcr " +
+	"on dsc.EP_NAME = dcr.EP_NAME and GROUP_TYPE = 'DB' order by  dsc.ep_seqno asc;"
+
+type reconnectFilter struct {
+}
+
+// 一定抛错
+func (rf *reconnectFilter) autoReconnect(connection *DmConnection, err error) error {
+	if dmErr, ok := err.(*DmError); ok {
+		if dmErr.ErrCode == ECGO_COMMUNITION_ERROR.ErrCode {
+			return rf.reconnect(connection, dmErr.Error())
+		}
+	}
+	return err
+}
+
+// 一定抛错
+func (rf *reconnectFilter) reconnect(connection *DmConnection, reason string) error {
+	// 读写分离,重连需要处理备机
+	var err error
+	if connection.dmConnector.rwSeparate {
+		err = RWUtil.reconnect(connection)
+	} else {
+		err = connection.reconnect()
+	}
+
+	if err != nil {
+		return ECGO_CONNECTION_SWITCH_FAILED.addDetailln(reason).throw()
+	}
+
+	// 重连成功
+	return ECGO_CONNECTION_SWITCHED.addDetailln(reason).throw()
+}
+
+func (rf *reconnectFilter) loadDscEpSites(conn *DmConnection) []*ep {
+	stmt, rs, err := conn.driverQuery(SQL_GET_DSC_EP_SITE)
+	if err != nil {
+		return nil
+	}
+	defer func() {
+		rs.close()
+		stmt.close()
+	}()
+	epList := make([]*ep, 0)
+	dest := make([]driver.Value, 4)
+	for err = rs.next(dest); err != io.EOF; err = rs.next(dest) {
+		ep := newEP(dest[1].(string), dest[2].(int32))
+		ep.epSeqno = dest[0].(int32)
+		if util.StringUtil.EqualsIgnoreCase(dest[3].(string), "OK") {
+			ep.epStatus = EP_STATUS_OK
+		} else {
+			ep.epStatus = EP_STATUS_ERROR
+		}
+		epList = append(epList, ep)
+	}
+	return epList
+}
+
+func (rf *reconnectFilter) checkAndRecover(conn *DmConnection) error {
+	if conn.dmConnector.doSwitch != DO_SWITCH_WHEN_EP_RECOVER {
+		return nil
+	}
+	// check trx finish
+	if !conn.trxFinish {
+		return nil
+	}
+	var curIndex = conn.getIndexOnEPGroup()
+	if curIndex == 0 || (time.Now().UnixNano()/1000000-conn.recoverInfo.checkEpRecoverTs) < int64(conn.dmConnector.switchInterval) {
+		return nil
+	}
+	// check db recover
+	var dscEps []*ep
+	if conn.dmConnector.cluster == CLUSTER_TYPE_DSC {
+		dscEps = rf.loadDscEpSites(conn)
+	}
+	if dscEps == nil || len(dscEps) == 0 {
+		return nil
+	}
+	var recover = false
+	for _, okEp := range dscEps {
+		if okEp.epStatus != EP_STATUS_OK {
+			continue
+		}
+		for i := int32(0); i < curIndex; i++ {
+			ep := conn.dmConnector.group.epList[i]
+			if okEp.host == ep.host && okEp.port == ep.port {
+				recover = true
+				break
+			}
+		}
+		if recover {
+			break
+		}
+	}
+
+	conn.recoverInfo.checkEpRecoverTs = time.Now().UnixNano() / 1000000
+	if !recover {
+		return nil
+	}
+	// do reconnect
+	return conn.reconnect()
+}
+
+// DmDriver
+func (rf *reconnectFilter) DmDriverOpen(filterChain *filterChain, d *DmDriver, dsn string) (*DmConnection, error) {
+	return filterChain.DmDriverOpen(d, dsn)
+}
+
+func (rf *reconnectFilter) DmDriverOpenConnector(filterChain *filterChain, d *DmDriver, dsn string) (*DmConnector, error) {
+	return filterChain.DmDriverOpenConnector(d, dsn)
+}
+
+// DmConnector
+func (rf *reconnectFilter) DmConnectorConnect(filterChain *filterChain, c *DmConnector, ctx context.Context) (*DmConnection, error) {
+	return filterChain.DmConnectorConnect(c, ctx)
+}
+
+func (rf *reconnectFilter) DmConnectorDriver(filterChain *filterChain, c *DmConnector) *DmDriver {
+	return filterChain.DmConnectorDriver(c)
+}
+
+// DmConnection
+func (rf *reconnectFilter) DmConnectionBegin(filterChain *filterChain, c *DmConnection) (*DmConnection, error) {
+	dc, err := filterChain.DmConnectionBegin(c)
+	if err != nil {
+		return nil, rf.autoReconnect(c, err)
+	}
+	return dc, err
+}
+
+func (rf *reconnectFilter) DmConnectionBeginTx(filterChain *filterChain, c *DmConnection, ctx context.Context, opts driver.TxOptions) (*DmConnection, error) {
+	dc, err := filterChain.DmConnectionBeginTx(c, ctx, opts)
+	if err != nil {
+		return nil, rf.autoReconnect(c, err)
+	}
+	return dc, err
+}
+
+func (rf *reconnectFilter) DmConnectionCommit(filterChain *filterChain, c *DmConnection) error {
+	if err := filterChain.DmConnectionCommit(c); err != nil {
+		return rf.autoReconnect(c, err)
+	}
+	if err := rf.checkAndRecover(c); err != nil {
+		return rf.autoReconnect(c, err)
+	}
+	return nil
+}
+
+func (rf *reconnectFilter) DmConnectionRollback(filterChain *filterChain, c *DmConnection) error {
+	err := filterChain.DmConnectionRollback(c)
+	if err != nil {
+		err = rf.autoReconnect(c, err)
+	}
+
+	return err
+}
+
+func (rf *reconnectFilter) DmConnectionClose(filterChain *filterChain, c *DmConnection) error {
+	err := filterChain.DmConnectionClose(c)
+	if err != nil {
+		err = rf.autoReconnect(c, err)
+	}
+
+	return err
+}
+
+func (rf *reconnectFilter) DmConnectionPing(filterChain *filterChain, c *DmConnection, ctx context.Context) error {
+	err := filterChain.DmConnectionPing(c, ctx)
+	if err != nil {
+		err = rf.autoReconnect(c, err)
+	}
+
+	return err
+}
+
+func (rf *reconnectFilter) DmConnectionExec(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (*DmResult, error) {
+	if err := rf.checkAndRecover(c); err != nil {
+		return nil, rf.autoReconnect(c, err)
+	}
+	dr, err := filterChain.DmConnectionExec(c, query, args)
+	if err != nil {
+		return nil, rf.autoReconnect(c, err)
+	}
+
+	return dr, err
+}
+
+func (rf *reconnectFilter) DmConnectionExecContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmResult, error) {
+	if err := rf.checkAndRecover(c); err != nil {
+		return nil, rf.autoReconnect(c, err)
+	}
+	dr, err := filterChain.DmConnectionExecContext(c, ctx, query, args)
+	if err != nil {
+		return nil, rf.autoReconnect(c, err)
+	}
+
+	return dr, err
+}
+
+func (rf *reconnectFilter) DmConnectionQuery(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (*DmRows, error) {
+	if err := rf.checkAndRecover(c); err != nil {
+		return nil, rf.autoReconnect(c, err)
+	}
+	dr, err := filterChain.DmConnectionQuery(c, query, args)
+	if err != nil {
+		return nil, rf.autoReconnect(c, err)
+	}
+
+	return dr, err
+}
+
+func (rf *reconnectFilter) DmConnectionQueryContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmRows, error) {
+	if err := rf.checkAndRecover(c); err != nil {
+		return nil, rf.autoReconnect(c, err)
+	}
+	dr, err := filterChain.DmConnectionQueryContext(c, ctx, query, args)
+	if err != nil {
+		return nil, rf.autoReconnect(c, err)
+	}
+
+	return dr, err
+}
+
+func (rf *reconnectFilter) DmConnectionPrepare(filterChain *filterChain, c *DmConnection, query string) (*DmStatement, error) {
+	ds, err := filterChain.DmConnectionPrepare(c, query)
+	if err != nil {
+		return nil, rf.autoReconnect(c, err)
+	}
+
+	return ds, err
+}
+
+func (rf *reconnectFilter) DmConnectionPrepareContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string) (*DmStatement, error) {
+	ds, err := filterChain.DmConnectionPrepareContext(c, ctx, query)
+	if err != nil {
+		return nil, rf.autoReconnect(c, err)
+	}
+
+	return ds, err
+}
+
+func (rf *reconnectFilter) DmConnectionResetSession(filterChain *filterChain, c *DmConnection, ctx context.Context) error {
+	err := filterChain.DmConnectionResetSession(c, ctx)
+	if err != nil {
+		err = rf.autoReconnect(c, err)
+	}
+
+	return err
+}
+
+func (rf *reconnectFilter) DmConnectionCheckNamedValue(filterChain *filterChain, c *DmConnection, nv *driver.NamedValue) error {
+	err := filterChain.DmConnectionCheckNamedValue(c, nv)
+	if err != nil {
+		err = rf.autoReconnect(c, err)
+	}
+
+	return err
+}
+
+// DmStatement
+func (rf *reconnectFilter) DmStatementClose(filterChain *filterChain, s *DmStatement) error {
+	err := filterChain.DmStatementClose(s)
+	if err != nil {
+		err = rf.autoReconnect(s.dmConn, err)
+	}
+
+	return err
+}
+
+func (rf *reconnectFilter) DmStatementNumInput(filterChain *filterChain, s *DmStatement) int {
+	var ret int
+	defer func() {
+		err := recover()
+		if err != nil {
+			rf.autoReconnect(s.dmConn, err.(error))
+			ret = 0
+		}
+	}()
+	ret = filterChain.DmStatementNumInput(s)
+	return ret
+}
+
+func (rf *reconnectFilter) DmStatementExec(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmResult, error) {
+	if err := rf.checkAndRecover(s.dmConn); err != nil {
+		return nil, rf.autoReconnect(s.dmConn, err)
+	}
+	dr, err := filterChain.DmStatementExec(s, args)
+	if err != nil {
+		return nil, rf.autoReconnect(s.dmConn, err)
+	}
+
+	return dr, err
+}
+
+func (rf *reconnectFilter) DmStatementExecContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmResult, error) {
+	if err := rf.checkAndRecover(s.dmConn); err != nil {
+		return nil, rf.autoReconnect(s.dmConn, err)
+	}
+	dr, err := filterChain.DmStatementExecContext(s, ctx, args)
+	if err != nil {
+		return nil, rf.autoReconnect(s.dmConn, err)
+	}
+
+	return dr, err
+}
+
+func (rf *reconnectFilter) DmStatementQuery(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmRows, error) {
+	if err := rf.checkAndRecover(s.dmConn); err != nil {
+		return nil, rf.autoReconnect(s.dmConn, err)
+	}
+	dr, err := filterChain.DmStatementQuery(s, args)
+	if err != nil {
+		return nil, rf.autoReconnect(s.dmConn, err)
+	}
+
+	return dr, err
+}
+
+func (rf *reconnectFilter) DmStatementQueryContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmRows, error) {
+	if err := rf.checkAndRecover(s.dmConn); err != nil {
+		return nil, rf.autoReconnect(s.dmConn, err)
+	}
+	dr, err := filterChain.DmStatementQueryContext(s, ctx, args)
+	if err != nil {
+		return nil, rf.autoReconnect(s.dmConn, err)
+	}
+
+	return dr, err
+}
+
+func (rf *reconnectFilter) DmStatementCheckNamedValue(filterChain *filterChain, s *DmStatement, nv *driver.NamedValue) error {
+	err := filterChain.DmStatementCheckNamedValue(s, nv)
+	if err != nil {
+		err = rf.autoReconnect(s.dmConn, err)
+	}
+
+	return err
+}
+
+// DmResult
+func (rf *reconnectFilter) DmResultLastInsertId(filterChain *filterChain, r *DmResult) (int64, error) {
+	i, err := filterChain.DmResultLastInsertId(r)
+	if err != nil {
+		err = rf.autoReconnect(r.dmStmt.dmConn, err)
+		return 0, err
+	}
+
+	return i, err
+}
+
+func (rf *reconnectFilter) DmResultRowsAffected(filterChain *filterChain, r *DmResult) (int64, error) {
+	i, err := filterChain.DmResultRowsAffected(r)
+	if err != nil {
+		err = rf.autoReconnect(r.dmStmt.dmConn, err)
+		return 0, err
+	}
+
+	return i, err
+}
+
+// DmRows
+func (rf *reconnectFilter) DmRowsColumns(filterChain *filterChain, r *DmRows) []string {
+	var ret []string
+	defer func() {
+		err := recover()
+		if err != nil {
+			rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err.(error))
+			ret = nil
+		}
+	}()
+	ret = filterChain.DmRowsColumns(r)
+	return ret
+}
+
+func (rf *reconnectFilter) DmRowsClose(filterChain *filterChain, r *DmRows) error {
+	err := filterChain.DmRowsClose(r)
+	if err != nil {
+		err = rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err)
+	}
+
+	return err
+}
+
+func (rf *reconnectFilter) DmRowsNext(filterChain *filterChain, r *DmRows, dest []driver.Value) error {
+	err := filterChain.DmRowsNext(r, dest)
+	if err != nil {
+		err = rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err)
+	}
+
+	return err
+}
+
+func (rf *reconnectFilter) DmRowsHasNextResultSet(filterChain *filterChain, r *DmRows) bool {
+	var ret bool
+	defer func() {
+		err := recover()
+		if err != nil {
+			rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err.(error))
+			ret = false
+		}
+	}()
+	ret = filterChain.DmRowsHasNextResultSet(r)
+	return ret
+}
+
+func (rf *reconnectFilter) DmRowsNextResultSet(filterChain *filterChain, r *DmRows) error {
+	err := filterChain.DmRowsNextResultSet(r)
+	if err != nil {
+		err = rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err)
+	}
+
+	return err
+}
+
+func (rf *reconnectFilter) DmRowsColumnTypeScanType(filterChain *filterChain, r *DmRows, index int) reflect.Type {
+	var ret reflect.Type
+	defer func() {
+		err := recover()
+		if err != nil {
+			rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err.(error))
+			ret = scanTypeUnknown
+		}
+	}()
+	ret = filterChain.DmRowsColumnTypeScanType(r, index)
+	return ret
+}
+
+func (rf *reconnectFilter) DmRowsColumnTypeDatabaseTypeName(filterChain *filterChain, r *DmRows, index int) string {
+	var ret string
+	defer func() {
+		err := recover()
+		if err != nil {
+			rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err.(error))
+			ret = ""
+		}
+	}()
+	ret = filterChain.DmRowsColumnTypeDatabaseTypeName(r, index)
+	return ret
+}
+
+func (rf *reconnectFilter) DmRowsColumnTypeLength(filterChain *filterChain, r *DmRows, index int) (length int64, ok bool) {
+	defer func() {
+		err := recover()
+		if err != nil {
+			rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err.(error))
+			length, ok = 0, false
+		}
+	}()
+	return filterChain.DmRowsColumnTypeLength(r, index)
+}
+
+func (rf *reconnectFilter) DmRowsColumnTypeNullable(filterChain *filterChain, r *DmRows, index int) (nullable, ok bool) {
+	defer func() {
+		err := recover()
+		if err != nil {
+			rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err.(error))
+			nullable, ok = false, false
+		}
+	}()
+	return filterChain.DmRowsColumnTypeNullable(r, index)
+}
+
+func (rf *reconnectFilter) DmRowsColumnTypePrecisionScale(filterChain *filterChain, r *DmRows, index int) (precision, scale int64, ok bool) {
+	defer func() {
+		err := recover()
+		if err != nil {
+			rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err.(error))
+			precision, scale, ok = 0, 0, false
+		}
+	}()
+	return filterChain.DmRowsColumnTypePrecisionScale(r, index)
+}

+ 310 - 0
zg.go

@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package dm
+
+import (
+	"context"
+	"database/sql/driver"
+	"reflect"
+)
+
+type rwFilter struct {
+}
+
+//DmDriver
+func (rwf *rwFilter) DmDriverOpen(filterChain *filterChain, d *DmDriver, dsn string) (*DmConnection, error) {
+	return filterChain.DmDriverOpen(d, dsn)
+}
+
+func (rwf *rwFilter) DmDriverOpenConnector(filterChain *filterChain, d *DmDriver, dsn string) (*DmConnector, error) {
+	return filterChain.DmDriverOpenConnector(d, dsn)
+}
+
+//DmConnector
+func (rwf *rwFilter) DmConnectorConnect(filterChain *filterChain, c *DmConnector, ctx context.Context) (*DmConnection, error) {
+	return RWUtil.connect(c, ctx)
+}
+
+func (rwf *rwFilter) DmConnectorDriver(filterChain *filterChain, c *DmConnector) *DmDriver {
+	return filterChain.DmConnectorDriver(c)
+}
+
+//DmConnection
+func (rwf *rwFilter) DmConnectionBegin(filterChain *filterChain, c *DmConnection) (*DmConnection, error) {
+	if RWUtil.isStandbyAlive(c) {
+		_, err := c.rwInfo.connStandby.begin()
+		if err != nil {
+			RWUtil.afterExceptionOnStandby(c, err)
+		}
+	}
+
+	return filterChain.DmConnectionBegin(c)
+}
+
+func (rwf *rwFilter) DmConnectionBeginTx(filterChain *filterChain, c *DmConnection, ctx context.Context, opts driver.TxOptions) (*DmConnection, error) {
+	if RWUtil.isStandbyAlive(c) {
+		_, err := c.rwInfo.connStandby.beginTx(ctx, opts)
+		if err != nil {
+			RWUtil.afterExceptionOnStandby(c, err)
+		}
+	}
+
+	return filterChain.DmConnectionBeginTx(c, ctx, opts)
+}
+
+func (rwf *rwFilter) DmConnectionCommit(filterChain *filterChain, c *DmConnection) error {
+	if RWUtil.isStandbyAlive(c) {
+		err := c.rwInfo.connStandby.commit()
+		if err != nil {
+			RWUtil.afterExceptionOnStandby(c, err)
+		}
+	}
+
+	return filterChain.DmConnectionCommit(c)
+}
+
+func (rwf *rwFilter) DmConnectionRollback(filterChain *filterChain, c *DmConnection) error {
+	if RWUtil.isStandbyAlive(c) {
+		err := c.rwInfo.connStandby.rollback()
+		if err != nil {
+			RWUtil.afterExceptionOnStandby(c, err)
+		}
+	}
+
+	return filterChain.DmConnectionRollback(c)
+}
+
+func (rwf *rwFilter) DmConnectionClose(filterChain *filterChain, c *DmConnection) error {
+	if RWUtil.isStandbyAlive(c) {
+		err := c.rwInfo.connStandby.close()
+		if err != nil {
+			RWUtil.afterExceptionOnStandby(c, err)
+		}
+	}
+
+	return filterChain.DmConnectionClose(c)
+}
+
+func (rwf *rwFilter) DmConnectionPing(filterChain *filterChain, c *DmConnection, ctx context.Context) error {
+	return filterChain.DmConnectionPing(c, ctx)
+}
+
+func (rwf *rwFilter) DmConnectionExec(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (*DmResult, error) {
+	ret, err := RWUtil.executeByConn(c, query, func() (interface{}, error) {
+		return c.rwInfo.connCurrent.exec(query, args)
+	}, func(otherConn *DmConnection) (interface{}, error) {
+		return otherConn.exec(query, args)
+	})
+	if err != nil {
+		return nil, err
+	}
+	return ret.(*DmResult), nil
+}
+
+func (rwf *rwFilter) DmConnectionExecContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmResult, error) {
+	ret, err := RWUtil.executeByConn(c, query, func() (interface{}, error) {
+		return c.rwInfo.connCurrent.execContext(ctx, query, args)
+	}, func(otherConn *DmConnection) (interface{}, error) {
+		return otherConn.execContext(ctx, query, args)
+	})
+	if err != nil {
+		return nil, err
+	}
+	return ret.(*DmResult), nil
+}
+
+func (rwf *rwFilter) DmConnectionQuery(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (*DmRows, error) {
+	ret, err := RWUtil.executeByConn(c, query, func() (interface{}, error) {
+		return c.rwInfo.connCurrent.query(query, args)
+	}, func(otherConn *DmConnection) (interface{}, error) {
+		return otherConn.query(query, args)
+	})
+	if err != nil {
+		return nil, err
+	}
+	return ret.(*DmRows), nil
+}
+
+func (rwf *rwFilter) DmConnectionQueryContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmRows, error) {
+	ret, err := RWUtil.executeByConn(c, query, func() (interface{}, error) {
+		return c.rwInfo.connCurrent.queryContext(ctx, query, args)
+	}, func(otherConn *DmConnection) (interface{}, error) {
+		return otherConn.queryContext(ctx, query, args)
+	})
+	if err != nil {
+		return nil, err
+	}
+	return ret.(*DmRows), nil
+}
+
+func (rwf *rwFilter) DmConnectionPrepare(filterChain *filterChain, c *DmConnection, query string) (*DmStatement, error) {
+	stmt, err := c.prepare(query)
+	if err != nil {
+		return nil, err
+	}
+	stmt.rwInfo.stmtCurrent = stmt
+	stmt.rwInfo.readOnly = RWUtil.checkReadonlyByStmt(stmt)
+	if RWUtil.isCreateStandbyStmt(stmt) {
+		stmt.rwInfo.stmtStandby, err = c.rwInfo.connStandby.prepare(query)
+		if err == nil {
+			stmt.rwInfo.stmtCurrent = stmt.rwInfo.stmtStandby
+		} else {
+			RWUtil.afterExceptionOnStandby(c, err)
+		}
+	}
+	return stmt, nil
+}
+
+func (rwf *rwFilter) DmConnectionPrepareContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string) (*DmStatement, error) {
+	stmt, err := c.prepareContext(ctx, query)
+	if err != nil {
+		return nil, err
+	}
+	stmt.rwInfo.stmtCurrent = stmt
+	stmt.rwInfo.readOnly = RWUtil.checkReadonlyByStmt(stmt)
+	if RWUtil.isCreateStandbyStmt(stmt) {
+		stmt.rwInfo.stmtStandby, err = c.rwInfo.connStandby.prepareContext(ctx, query)
+		if err == nil {
+			stmt.rwInfo.stmtCurrent = stmt.rwInfo.stmtStandby
+		} else {
+			RWUtil.afterExceptionOnStandby(c, err)
+		}
+	}
+	return stmt, nil
+}
+
+func (rwf *rwFilter) DmConnectionResetSession(filterChain *filterChain, c *DmConnection, ctx context.Context) error {
+	if RWUtil.isStandbyAlive(c) {
+		err := c.rwInfo.connStandby.resetSession(ctx)
+		if err != nil {
+			RWUtil.afterExceptionOnStandby(c, err)
+		}
+	}
+
+	return filterChain.DmConnectionResetSession(c, ctx)
+}
+
+func (rwf *rwFilter) DmConnectionCheckNamedValue(filterChain *filterChain, c *DmConnection, nv *driver.NamedValue) error {
+	return filterChain.DmConnectionCheckNamedValue(c, nv)
+}
+
+//DmStatement
+func (rwf *rwFilter) DmStatementClose(filterChain *filterChain, s *DmStatement) error {
+	if RWUtil.isStandbyStatementValid(s) {
+		err := s.rwInfo.stmtStandby.close()
+		if err != nil {
+			RWUtil.afterExceptionOnStandby(s.dmConn, err)
+		}
+	}
+
+	return filterChain.DmStatementClose(s)
+}
+
+func (rwf *rwFilter) DmStatementNumInput(filterChain *filterChain, s *DmStatement) int {
+	return filterChain.DmStatementNumInput(s)
+}
+
+func (rwf *rwFilter) DmStatementExec(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmResult, error) {
+	ret, err := RWUtil.executeByStmt(s, func() (interface{}, error) {
+		return s.rwInfo.stmtCurrent.exec(args)
+	}, func(otherStmt *DmStatement) (interface{}, error) {
+		return otherStmt.exec(args)
+	})
+	if err != nil {
+		return nil, err
+	}
+	return ret.(*DmResult), nil
+}
+
+func (rwf *rwFilter) DmStatementExecContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmResult, error) {
+	ret, err := RWUtil.executeByStmt(s, func() (interface{}, error) {
+		return s.rwInfo.stmtCurrent.execContext(ctx, args)
+	}, func(otherStmt *DmStatement) (interface{}, error) {
+		return otherStmt.execContext(ctx, args)
+	})
+	if err != nil {
+		return nil, err
+	}
+	return ret.(*DmResult), nil
+}
+
+func (rwf *rwFilter) DmStatementQuery(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmRows, error) {
+	ret, err := RWUtil.executeByStmt(s, func() (interface{}, error) {
+		return s.rwInfo.stmtCurrent.query(args)
+	}, func(otherStmt *DmStatement) (interface{}, error) {
+		return otherStmt.query(args)
+	})
+	if err != nil {
+		return nil, err
+	}
+	return ret.(*DmRows), nil
+}
+
+func (rwf *rwFilter) DmStatementQueryContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmRows, error) {
+	ret, err := RWUtil.executeByStmt(s, func() (interface{}, error) {
+		return s.rwInfo.stmtCurrent.queryContext(ctx, args)
+	}, func(otherStmt *DmStatement) (interface{}, error) {
+		return otherStmt.queryContext(ctx, args)
+	})
+	if err != nil {
+		return nil, err
+	}
+	return ret.(*DmRows), nil
+}
+
+func (rwf *rwFilter) DmStatementCheckNamedValue(filterChain *filterChain, s *DmStatement, nv *driver.NamedValue) error {
+	return filterChain.DmStatementCheckNamedValue(s, nv)
+}
+
+//DmResult
+func (rwf *rwFilter) DmResultLastInsertId(filterChain *filterChain, r *DmResult) (int64, error) {
+	return filterChain.DmResultLastInsertId(r)
+}
+
+func (rwf *rwFilter) DmResultRowsAffected(filterChain *filterChain, r *DmResult) (int64, error) {
+	return filterChain.DmResultRowsAffected(r)
+}
+
+//DmRows
+func (rwf *rwFilter) DmRowsColumns(filterChain *filterChain, r *DmRows) []string {
+	return filterChain.DmRowsColumns(r)
+}
+
+func (rwf *rwFilter) DmRowsClose(filterChain *filterChain, r *DmRows) error {
+	return filterChain.DmRowsClose(r)
+}
+
+func (rwf *rwFilter) DmRowsNext(filterChain *filterChain, r *DmRows, dest []driver.Value) error {
+	return filterChain.DmRowsNext(r, dest)
+}
+
+func (rwf *rwFilter) DmRowsHasNextResultSet(filterChain *filterChain, r *DmRows) bool {
+	return filterChain.DmRowsHasNextResultSet(r)
+}
+
+func (rwf *rwFilter) DmRowsNextResultSet(filterChain *filterChain, r *DmRows) error {
+	return filterChain.DmRowsNextResultSet(r)
+}
+
+func (rwf *rwFilter) DmRowsColumnTypeScanType(filterChain *filterChain, r *DmRows, index int) reflect.Type {
+	return filterChain.DmRowsColumnTypeScanType(r, index)
+}
+
+func (rwf *rwFilter) DmRowsColumnTypeDatabaseTypeName(filterChain *filterChain, r *DmRows, index int) string {
+	return filterChain.DmRowsColumnTypeDatabaseTypeName(r, index)
+}
+
+func (rwf *rwFilter) DmRowsColumnTypeLength(filterChain *filterChain, r *DmRows, index int) (length int64, ok bool) {
+	return filterChain.DmRowsColumnTypeLength(r, index)
+}
+
+func (rwf *rwFilter) DmRowsColumnTypeNullable(filterChain *filterChain, r *DmRows, index int) (nullable, ok bool) {
+	return filterChain.DmRowsColumnTypeNullable(r, index)
+}
+
+func (rwf *rwFilter) DmRowsColumnTypePrecisionScale(filterChain *filterChain, r *DmRows, index int) (precision, scale int64, ok bool) {
+	return filterChain.DmRowsColumnTypePrecisionScale(r, index)
+}

+ 607 - 0
zh.go

@@ -0,0 +1,607 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package dm
+
+import (
+	"bytes"
+	"context"
+	"database/sql/driver"
+	"fmt"
+	"reflect"
+	"time"
+)
+
+type statFilter struct {
+}
+
+//DmDriver
+func (sf *statFilter) DmDriverOpen(filterChain *filterChain, d *DmDriver, dsn string) (*DmConnection, error) {
+	conn, err := filterChain.DmDriverOpen(d, dsn)
+	if err != nil {
+		return nil, err
+	}
+	conn.statInfo.init(conn)
+	conn.statInfo.setConstructNano()
+	conn.statInfo.getConnStat().incrementConn()
+	return conn, nil
+}
+
+func (sf *statFilter) DmDriverOpenConnector(filterChain *filterChain, d *DmDriver, dsn string) (*DmConnector, error) {
+	return filterChain.DmDriverOpenConnector(d, dsn)
+}
+
+//DmConnector
+func (sf *statFilter) DmConnectorConnect(filterChain *filterChain, c *DmConnector, ctx context.Context) (*DmConnection, error) {
+	conn, err := filterChain.DmConnectorConnect(c, ctx)
+	if err != nil {
+		return nil, err
+	}
+	conn.statInfo.init(conn)
+	conn.statInfo.setConstructNano()
+	conn.statInfo.getConnStat().incrementConn()
+	return conn, nil
+}
+
+func (sf *statFilter) DmConnectorDriver(filterChain *filterChain, c *DmConnector) *DmDriver {
+	return filterChain.DmConnectorDriver(c)
+}
+
+//DmConnection
+func (sf *statFilter) DmConnectionBegin(filterChain *filterChain, c *DmConnection) (*DmConnection, error) {
+	return filterChain.DmConnectionBegin(c)
+}
+
+func (sf *statFilter) DmConnectionBeginTx(filterChain *filterChain, c *DmConnection, ctx context.Context, opts driver.TxOptions) (*DmConnection, error) {
+	return filterChain.DmConnectionBeginTx(c, ctx, opts)
+}
+
+func (sf *statFilter) DmConnectionCommit(filterChain *filterChain, c *DmConnection) error {
+	err := filterChain.DmConnectionCommit(c)
+	if err != nil {
+		return err
+	}
+	c.statInfo.getConnStat().incrementCommitCount()
+	return nil
+}
+
+func (sf *statFilter) DmConnectionRollback(filterChain *filterChain, c *DmConnection) error {
+	err := filterChain.DmConnectionRollback(c)
+	if err != nil {
+		return err
+	}
+	c.statInfo.getConnStat().incrementRollbackCount()
+	return nil
+}
+
+func (sf *statFilter) DmConnectionClose(filterChain *filterChain, c *DmConnection) error {
+	if !c.closed.IsSet() {
+		c.statInfo.getConnStat().decrementStmtByActiveStmtCount(int64(getActiveStmtCount(c)))
+		c.statInfo.getConnStat().decrementConn()
+	}
+
+	return filterChain.DmConnectionClose(c)
+}
+
+func (sf *statFilter) DmConnectionPing(filterChain *filterChain, c *DmConnection, ctx context.Context) error {
+	return c.ping(ctx)
+}
+
+func (sf *statFilter) DmConnectionExec(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (*DmResult, error) {
+	connExecBefore(c, query)
+	dr, err := filterChain.DmConnectionExec(c, query, args)
+	if err != nil {
+		connExecuteErrorAfter(c, args, err)
+		return nil, err
+	}
+	connExecAfter(c, query, args, int(dr.affectedRows))
+	return dr, nil
+}
+
+func (sf *statFilter) DmConnectionExecContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmResult, error) {
+	connExecBefore(c, query)
+	dr, err := filterChain.DmConnectionExecContext(c, ctx, query, args)
+	if err != nil {
+		connExecuteErrorAfter(c, args, err)
+		return nil, err
+	}
+	connExecAfter(c, query, args, int(dr.affectedRows))
+	return dr, nil
+}
+
+func (sf *statFilter) DmConnectionQuery(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (*DmRows, error) {
+	connQueryBefore(c, query)
+	dr, err := filterChain.DmConnectionQuery(c, query, args)
+	if err != nil {
+		connExecuteErrorAfter(c, args, err)
+		return nil, err
+	}
+	connQueryAfter(c, query, args, dr)
+	return dr, nil
+}
+
+func (sf *statFilter) DmConnectionQueryContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmRows, error) {
+	connQueryBefore(c, query)
+	dr, err := filterChain.DmConnectionQueryContext(c, ctx, query, args)
+	if err != nil {
+		connExecuteErrorAfter(c, args, err)
+		return nil, err
+	}
+	connQueryAfter(c, query, args, dr)
+	return dr, nil
+}
+
+func (sf *statFilter) DmConnectionPrepare(filterChain *filterChain, c *DmConnection, query string) (*DmStatement, error) {
+	stmt, err := filterChain.DmConnectionPrepare(c, query)
+	if err != nil {
+		return nil, err
+	}
+	statementCreateAfter(c, stmt)
+	return stmt, nil
+}
+
+func (sf *statFilter) DmConnectionPrepareContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string) (*DmStatement, error) {
+	stmt, err := filterChain.DmConnectionPrepareContext(c, ctx, query)
+	if err != nil {
+		return nil, err
+	}
+	statementCreateAfter(c, stmt)
+	return stmt, nil
+}
+
+func (sf *statFilter) DmConnectionResetSession(filterChain *filterChain, c *DmConnection, ctx context.Context) error {
+	return filterChain.DmConnectionResetSession(c, ctx)
+}
+
+func (sf *statFilter) DmConnectionCheckNamedValue(filterChain *filterChain, c *DmConnection, nv *driver.NamedValue) error {
+	return filterChain.DmConnectionCheckNamedValue(c, nv)
+}
+
+//DmStatement
+func (sf *statFilter) DmStatementClose(filterChain *filterChain, s *DmStatement) error {
+	if !s.closed {
+		statementCloseBefore(s)
+	}
+	return filterChain.DmStatementClose(s)
+}
+
+func (sf *statFilter) DmStatementNumInput(filterChain *filterChain, s *DmStatement) int {
+	return filterChain.DmStatementNumInput(s)
+}
+
+func (sf *statFilter) DmStatementExec(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmResult, error) {
+	stmtExecBefore(s)
+	dr, err := filterChain.DmStatementExec(s, args)
+	if err != nil {
+		statementExecuteErrorAfter(s, args, err)
+		return nil, err
+	}
+	stmtExecAfter(s, args, int(dr.affectedRows))
+	return dr, nil
+}
+
+func (sf *statFilter) DmStatementExecContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmResult, error) {
+	stmtExecBefore(s)
+	dr, err := filterChain.DmStatementExecContext(s, ctx, args)
+	if err != nil {
+		statementExecuteErrorAfter(s, args, err)
+		return nil, err
+	}
+	stmtExecAfter(s, args, int(dr.affectedRows))
+	return dr, nil
+}
+
+func (sf *statFilter) DmStatementQuery(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmRows, error) {
+	stmtQueryBefore(s)
+	dr, err := filterChain.DmStatementQuery(s, args)
+	if err != nil {
+		statementExecuteErrorAfter(s, args, err)
+		return nil, err
+	}
+	stmtQueryAfter(s, args, dr)
+	return dr, nil
+}
+
+func (sf *statFilter) DmStatementQueryContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmRows, error) {
+	stmtQueryBefore(s)
+	dr, err := filterChain.DmStatementQueryContext(s, ctx, args)
+	if err != nil {
+		statementExecuteErrorAfter(s, args, err)
+		return nil, err
+	}
+	stmtQueryAfter(s, args, dr)
+	return dr, nil
+}
+
+func (sf *statFilter) DmStatementCheckNamedValue(filterChain *filterChain, s *DmStatement, nv *driver.NamedValue) error {
+	return filterChain.DmStatementCheckNamedValue(s, nv)
+}
+
+//DmResult
+func (sf *statFilter) DmResultLastInsertId(filterChain *filterChain, r *DmResult) (int64, error) {
+	return filterChain.DmResultLastInsertId(r)
+}
+
+func (sf *statFilter) DmResultRowsAffected(filterChain *filterChain, r *DmResult) (int64, error) {
+	return filterChain.DmResultRowsAffected(r)
+}
+
+//DmRows
+func (sf *statFilter) DmRowsColumns(filterChain *filterChain, r *DmRows) []string {
+	return filterChain.DmRowsColumns(r)
+}
+
+func (sf *statFilter) DmRowsClose(filterChain *filterChain, r *DmRows) error {
+	if !r.CurrentRows.closed {
+		resultSetCloseBefore(r)
+	}
+	return filterChain.DmRowsClose(r)
+}
+
+func (sf *statFilter) DmRowsNext(filterChain *filterChain, r *DmRows, dest []driver.Value) error {
+	return filterChain.DmRowsNext(r, dest)
+}
+
+func (sf *statFilter) DmRowsHasNextResultSet(filterChain *filterChain, r *DmRows) bool {
+	return filterChain.DmRowsHasNextResultSet(r)
+}
+
+func (sf *statFilter) DmRowsNextResultSet(filterChain *filterChain, r *DmRows) error {
+	return filterChain.DmRowsNextResultSet(r)
+}
+
+func (sf *statFilter) DmRowsColumnTypeScanType(filterChain *filterChain, r *DmRows, index int) reflect.Type {
+	return filterChain.DmRowsColumnTypeScanType(r, index)
+}
+
+func (sf *statFilter) DmRowsColumnTypeDatabaseTypeName(filterChain *filterChain, r *DmRows, index int) string {
+	return filterChain.DmRowsColumnTypeDatabaseTypeName(r, index)
+}
+
+func (sf *statFilter) DmRowsColumnTypeLength(filterChain *filterChain, r *DmRows, index int) (length int64, ok bool) {
+	return filterChain.DmRowsColumnTypeLength(r, index)
+}
+
+func (sf *statFilter) DmRowsColumnTypeNullable(filterChain *filterChain, r *DmRows, index int) (nullable, ok bool) {
+	return filterChain.DmRowsColumnTypeNullable(r, index)
+}
+
+func (sf *statFilter) DmRowsColumnTypePrecisionScale(filterChain *filterChain, r *DmRows, index int) (precision, scale int64, ok bool) {
+	return filterChain.DmRowsColumnTypePrecisionScale(r, index)
+}
+
+func getActiveStmtCount(conn *DmConnection) int {
+	if conn.stmtMap == nil {
+		return 0
+	} else {
+		return len(conn.stmtMap)
+	}
+}
+
+func statementCreateAfter(conn *DmConnection, stmt *DmStatement) {
+	stmt.statInfo.setConstructNano()
+	conn.statInfo.getConnStat().incrementStmt()
+}
+
+func connExecBefore(conn *DmConnection, sql string) {
+	conn.statInfo.setLastExecuteSql(sql)
+	conn.statInfo.setFirstResultSet(false)
+	conn.statInfo.setLastExecuteType(ExecuteUpdate)
+	internalBeforeConnExecute(conn, sql)
+}
+
+func connExecAfter(conn *DmConnection, sql string, args interface{}, updateCount int) {
+	internalAfterConnExecute(conn, args, updateCount)
+}
+
+func connQueryBefore(conn *DmConnection, sql string) {
+	conn.statInfo.setLastExecuteSql(sql)
+	conn.statInfo.setFirstResultSet(true)
+	conn.statInfo.setLastExecuteType(ExecuteQuery)
+	internalBeforeConnExecute(conn, sql)
+}
+
+func connQueryAfter(conn *DmConnection, sql string, args interface{}, resultSet *DmRows) {
+	if resultSet != nil {
+		connResultSetCreateAfter(resultSet, conn)
+	}
+	internalAfterConnExecute(conn, args, 0)
+}
+
+func stmtExecBefore(stmt *DmStatement) {
+	stmt.statInfo.setLastExecuteSql(stmt.nativeSql)
+	stmt.statInfo.setFirstResultSet(false)
+	stmt.statInfo.setLastExecuteType(ExecuteUpdate)
+	internalBeforeStatementExecute(stmt, stmt.nativeSql)
+}
+
+func stmtExecAfter(stmt *DmStatement, args interface{}, updateCount int) {
+	internalAfterStatementExecute(stmt, args, updateCount)
+}
+
+func stmtQueryBefore(stmt *DmStatement) {
+	stmt.statInfo.setLastExecuteSql(stmt.nativeSql)
+	stmt.statInfo.setFirstResultSet(true)
+	stmt.statInfo.setLastExecuteType(ExecuteQuery)
+	internalBeforeStatementExecute(stmt, stmt.nativeSql)
+}
+
+func stmtQueryAfter(stmt *DmStatement, args interface{}, resultSet *DmRows) {
+	if resultSet != nil {
+		stmtResultSetCreateAfter(resultSet, stmt)
+	}
+	internalAfterStatementExecute(stmt, args, 0)
+}
+
+func internalBeforeConnExecute(conn *DmConnection, sql string) {
+	connStat := conn.statInfo.getConnStat()
+	connStat.incrementExecuteCount()
+	conn.statInfo.beforeExecute()
+
+	sqlStat := conn.statInfo.getSqlStat()
+	if sqlStat == nil || sqlStat.Removed == 1 || !(sqlStat.Sql == sql) {
+		sqlStat = connStat.createSqlStat(sql)
+		conn.statInfo.setSqlStat(sqlStat)
+	}
+
+	inTransaction := false
+	inTransaction = !conn.autoCommit
+
+	if sqlStat != nil {
+		sqlStat.ExecuteLastStartTime = time.Now().UnixNano()
+		sqlStat.incrementRunningCount()
+
+		if inTransaction {
+			sqlStat.incrementInTransactionCount()
+		}
+	}
+}
+
+func internalAfterConnExecute(conn *DmConnection, args interface{}, updateCount int) {
+	nowNano := time.Now().UnixNano()
+	nanos := nowNano - conn.statInfo.getLastExecuteStartNano()
+
+	conn.statInfo.afterExecute(nanos)
+
+	sqlStat := conn.statInfo.getSqlStat()
+
+	if sqlStat != nil {
+		sqlStat.incrementExecuteSuccessCount()
+
+		sqlStat.decrementRunningCount()
+
+		parameters := buildSlowParameters(args)
+
+		sqlStat.addExecuteTimeAndResultHoldTimeHistogramRecord(conn.statInfo.getLastExecuteType(), conn.statInfo.isFirstResultSet(),
+			nanos, parameters)
+
+		if !conn.statInfo.isFirstResultSet() &&
+			conn.statInfo.getLastExecuteType() == ExecuteUpdate {
+			if updateCount < 0 {
+				updateCount = 0
+			}
+			sqlStat.addUpdateCount(int64(updateCount))
+		}
+	}
+
+}
+
+func internalBeforeStatementExecute(stmt *DmStatement, sql string) {
+	connStat := stmt.dmConn.statInfo.getConnStat()
+	connStat.incrementExecuteCount()
+	stmt.statInfo.beforeExecute()
+
+	sqlStat := stmt.statInfo.getSqlStat()
+	if sqlStat == nil || sqlStat.Removed == 1 || !(sqlStat.Sql == sql) {
+		sqlStat = connStat.createSqlStat(sql)
+		stmt.statInfo.setSqlStat(sqlStat)
+	}
+
+	inTransaction := false
+	inTransaction = !stmt.dmConn.autoCommit
+
+	if sqlStat != nil {
+		sqlStat.ExecuteLastStartTime = time.Now().UnixNano()
+		sqlStat.incrementRunningCount()
+
+		if inTransaction {
+			sqlStat.incrementInTransactionCount()
+		}
+	}
+}
+
+func internalAfterStatementExecute(stmt *DmStatement, args interface{}, updateCount int) {
+	nowNano := time.Now().UnixNano()
+	nanos := nowNano - stmt.statInfo.getLastExecuteStartNano()
+
+	stmt.statInfo.afterExecute(nanos)
+
+	sqlStat := stmt.statInfo.getSqlStat()
+
+	if sqlStat != nil {
+		sqlStat.incrementExecuteSuccessCount()
+
+		sqlStat.decrementRunningCount()
+
+		parameters := ""
+		if stmt.paramCount > 0 {
+			parameters = buildStmtSlowParameters(stmt, args)
+		}
+		sqlStat.addExecuteTimeAndResultHoldTimeHistogramRecord(stmt.statInfo.getLastExecuteType(), stmt.statInfo.isFirstResultSet(),
+			nanos, parameters)
+
+		if (!stmt.statInfo.isFirstResultSet()) &&
+			stmt.statInfo.getLastExecuteType() == ExecuteUpdate {
+			updateCount := stmt.execInfo.updateCount
+			if updateCount < 0 {
+				updateCount = 0
+			}
+			sqlStat.addUpdateCount(updateCount)
+		}
+
+	}
+
+}
+
+func buildSlowParameters(args interface{}) string {
+	switch v := args.(type) {
+	case []driver.Value:
+		sb := bytes.NewBufferString("")
+		for i := 0; i < len(v); i++ {
+			if i != 0 {
+				sb.WriteString(",")
+			} else {
+				sb.WriteString("[")
+			}
+
+			sb.WriteString(fmt.Sprint(v[i]))
+		}
+
+		if len(v) > 0 {
+			sb.WriteString("]")
+		}
+		return sb.String()
+	case []driver.NamedValue:
+		sb := bytes.NewBufferString("")
+		for i := 0; i < len(v); i++ {
+			if i != 0 {
+				sb.WriteString(",")
+			} else {
+				sb.WriteString("[")
+			}
+
+			sb.WriteString(fmt.Sprint(v[i]))
+		}
+		if len(v) > 0 {
+			sb.WriteString("]")
+		}
+		return sb.String()
+	default:
+		return ""
+	}
+}
+
+func buildStmtSlowParameters(stmt *DmStatement, args interface{}) string {
+	switch v := args.(type) {
+	case []driver.Value:
+		sb := bytes.NewBufferString("")
+		for i := 0; i < int(stmt.paramCount); i++ {
+			if i != 0 {
+				sb.WriteString(",")
+			} else {
+				sb.WriteString("[")
+			}
+
+			sb.WriteString(fmt.Sprint(v[i]))
+		}
+		if len(v) > 0 {
+			sb.WriteString("]")
+		}
+		return sb.String()
+	case []driver.NamedValue:
+		sb := bytes.NewBufferString("")
+		for i := 0; i < int(stmt.paramCount); i++ {
+			if i != 0 {
+				sb.WriteString(",")
+			} else {
+				sb.WriteString("[")
+			}
+
+			sb.WriteString(fmt.Sprint(v[i]))
+		}
+		if len(v) > 0 {
+			sb.WriteString("]")
+		}
+		return sb.String()
+	default:
+		return ""
+	}
+}
+
+func connExecuteErrorAfter(conn *DmConnection, args interface{}, err error) {
+	nanos := time.Now().UnixNano() - conn.statInfo.getLastExecuteStartNano()
+	conn.statInfo.getConnStat().incrementErrorCount()
+	conn.statInfo.afterExecute(nanos)
+
+	// SQL
+	sqlStat := conn.statInfo.getSqlStat()
+	if sqlStat != nil {
+		sqlStat.decrementRunningCount()
+		sqlStat.error(err)
+		parameters := buildSlowParameters(args)
+		sqlStat.addExecuteTimeAndResultHoldTimeHistogramRecord(conn.statInfo.getLastExecuteType(), conn.statInfo.isFirstResultSet(),
+			nanos, parameters)
+	}
+
+}
+
+func statementExecuteErrorAfter(stmt *DmStatement, args interface{}, err error) {
+	nanos := time.Now().UnixNano() - stmt.statInfo.getLastExecuteStartNano()
+	stmt.dmConn.statInfo.getConnStat().incrementErrorCount()
+	stmt.statInfo.afterExecute(nanos)
+
+	// SQL
+	sqlStat := stmt.statInfo.getSqlStat()
+	if sqlStat != nil {
+		sqlStat.decrementRunningCount()
+		sqlStat.error(err)
+		parameters := ""
+		if stmt.paramCount > 0 {
+			parameters = buildStmtSlowParameters(stmt, args)
+		}
+		sqlStat.addExecuteTimeAndResultHoldTimeHistogramRecord(stmt.statInfo.getLastExecuteType(), stmt.statInfo.isFirstResultSet(),
+			nanos, parameters)
+	}
+
+}
+
+func statementCloseBefore(stmt *DmStatement) {
+	stmt.dmConn.statInfo.getConnStat().decrementStmt()
+}
+
+func connResultSetCreateAfter(dmdbResultSet *DmRows, conn *DmConnection) {
+	dmdbResultSet.statInfo.setSql(conn.statInfo.getLastExecuteSql())
+	dmdbResultSet.statInfo.setSqlStat(conn.statInfo.getSqlStat())
+	dmdbResultSet.statInfo.setConstructNano()
+}
+
+func stmtResultSetCreateAfter(dmdbResultSet *DmRows, stmt *DmStatement) {
+	dmdbResultSet.statInfo.setSql(stmt.statInfo.getLastExecuteSql())
+	dmdbResultSet.statInfo.setSqlStat(stmt.statInfo.getSqlStat())
+	dmdbResultSet.statInfo.setConstructNano()
+}
+
+func resultSetCloseBefore(resultSet *DmRows) {
+	nanos := time.Now().UnixNano() - resultSet.statInfo.getConstructNano()
+	fetchRowCount := getFetchedRows(resultSet)
+	sqlStat := resultSet.statInfo.getSqlStat()
+	if sqlStat != nil && resultSet.statInfo.getCloseCount() == 0 {
+		sqlStat.addFetchRowCount(fetchRowCount)
+		stmtExecuteNano := resultSet.statInfo.getLastExecuteTimeNano()
+		sqlStat.addResultSetHoldTimeNano2(stmtExecuteNano, nanos)
+		if resultSet.statInfo.getReadStringLength() > 0 {
+			sqlStat.addStringReadLength(resultSet.statInfo.getReadStringLength())
+		}
+		if resultSet.statInfo.getReadBytesLength() > 0 {
+			sqlStat.addReadBytesLength(resultSet.statInfo.getReadBytesLength())
+		}
+		if resultSet.statInfo.getOpenInputStreamCount() > 0 {
+			sqlStat.addInputStreamOpenCount(int64(resultSet.statInfo.getOpenInputStreamCount()))
+		}
+		if resultSet.statInfo.getOpenReaderCount() > 0 {
+			sqlStat.addReaderOpenCount(int64(resultSet.statInfo.getOpenReaderCount()))
+		}
+	}
+
+	resultSet.statInfo.incrementCloseCount()
+}
+
+func getFetchedRows(rs *DmRows) int64 {
+	if rs.CurrentRows.currentPos >= rs.CurrentRows.totalRowCount {
+		return rs.CurrentRows.totalRowCount
+	} else {
+		return rs.CurrentRows.currentPos + 1
+	}
+}

+ 1017 - 0
zi.go

@@ -0,0 +1,1017 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"bytes"
+	"io"
+	"math/big"
+	"strconv"
+	"strings"
+	"time"
+
+	"gitee.com/chunanyong/dm/util"
+)
+
+var G2DB g2db
+
+type g2db struct {
+}
+
+func (G2DB g2db) checkTinyint(val interface{}) error {
+	switch v := val.(type) {
+	case float64:
+		if v < float64(INT8_MIN) || v > float64(INT8_MAX) {
+			return ECGO_DATA_OVERFLOW.throw()
+		}
+	case DmDecimal:
+		if v.ToBigInt().Cmp(big.NewInt(int64(INT8_MIN))) < 0 ||
+			v.ToBigInt().Cmp(big.NewInt(int64(INT8_MAX))) > 0 {
+			return ECGO_DATA_OVERFLOW.throw()
+		}
+	}
+	return nil
+}
+
+func (G2DB g2db) checkSmallint(val interface{}) error {
+	switch v := val.(type) {
+	case float64:
+		if v < float64(INT16_MIN) || v > float64(INT16_MAX) {
+			return ECGO_DATA_OVERFLOW.throw()
+		}
+	case DmDecimal:
+		if v.ToBigInt().Cmp(big.NewInt(int64(INT16_MIN))) < 0 ||
+			v.ToBigInt().Cmp(big.NewInt(int64(INT16_MAX))) > 0 {
+			return ECGO_DATA_OVERFLOW.throw()
+		}
+	}
+	return nil
+}
+
+func (G2DB g2db) checkInt(val interface{}) error {
+	switch v := val.(type) {
+	case float64:
+		if v < float64(INT32_MIN) || v > float64(INT32_MAX) {
+			return ECGO_DATA_OVERFLOW.throw()
+		}
+	case DmDecimal:
+		if v.ToBigInt().Cmp(big.NewInt(int64(INT32_MIN))) < 0 ||
+			v.ToBigInt().Cmp(big.NewInt(int64(INT32_MAX))) > 0 {
+			return ECGO_DATA_OVERFLOW.throw()
+		}
+	}
+	return nil
+}
+
+func (G2DB g2db) checkBigint(val interface{}) error {
+	switch v := val.(type) {
+	case float64:
+		if v < float64(INT64_MIN) || v > float64(INT64_MAX) {
+			return ECGO_DATA_OVERFLOW.throw()
+		}
+	case DmDecimal:
+		if v.ToBigInt().Cmp(big.NewInt(INT64_MIN)) < 0 ||
+			v.ToBigInt().Cmp(big.NewInt(INT64_MAX)) > 0 {
+			return ECGO_DATA_OVERFLOW.throw()
+		}
+	}
+	return nil
+}
+
+func (G2DB g2db) checkReal(val interface{}) error {
+	switch v := val.(type) {
+	case float64:
+		if v < float64(FLOAT32_MIN) || v > float64(FLOAT32_MAX) {
+			return ECGO_DATA_OVERFLOW.throw()
+		}
+	case DmDecimal:
+		if v.ToBigFloat().Cmp(big.NewFloat(float64(FLOAT32_MIN))) < 0 ||
+			v.ToBigFloat().Cmp(big.NewFloat(float64(FLOAT32_MAX))) > 0 {
+			return ECGO_DATA_OVERFLOW.throw()
+		}
+	}
+	return nil
+}
+
+func (G2DB g2db) fromBool(val bool, param parameter, conn *DmConnection) ([]byte, error) {
+	switch param.colType {
+	case BOOLEAN, BIT, TINYINT, SMALLINT, INT, BIGINT, REAL, DOUBLE, DECIMAL, CHAR,
+		VARCHAR2, VARCHAR, CLOB:
+		if val {
+			return G2DB.fromInt64(1, param, conn)
+		} else {
+			return G2DB.fromInt64(0, param, conn)
+		}
+	case BINARY, VARBINARY, BLOB:
+		if val {
+			return Dm_build_1.Dm_build_179(byte(1)), nil
+		} else {
+			return Dm_build_1.Dm_build_179(byte(0)), nil
+		}
+	}
+	return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+}
+
+func (G2DB g2db) fromInt64(val int64, param parameter, conn *DmConnection) ([]byte, error) {
+
+	switch param.colType {
+	case BOOLEAN, BIT:
+		if val == 0 {
+			return Dm_build_1.Dm_build_179(byte(0)), nil
+		}
+
+		return Dm_build_1.Dm_build_179(byte(1)), nil
+
+	case TINYINT:
+		err := G2DB.checkTinyint(float64(val))
+
+		if err != nil {
+			return nil, err
+		}
+
+		return Dm_build_1.Dm_build_179(byte(val)), nil
+	case SMALLINT:
+		err := G2DB.checkSmallint(float64(val))
+
+		if err != nil {
+			return nil, err
+		}
+
+		return Dm_build_1.Dm_build_185(int16(val)), nil
+	case INT:
+		err := G2DB.checkInt(float64(val))
+
+		if err != nil {
+			return nil, err
+		}
+
+		return Dm_build_1.Dm_build_188(int32(val)), nil
+	case BIGINT:
+		err := G2DB.checkBigint(float64(val))
+
+		if err != nil {
+			return nil, err
+		}
+
+		return Dm_build_1.Dm_build_191(int64(val)), nil
+	case REAL:
+		err := G2DB.checkReal(float64(val))
+
+		if err != nil {
+			return nil, err
+		}
+
+		return Dm_build_1.Dm_build_194(float32(val)), nil
+	case DOUBLE:
+		return Dm_build_1.Dm_build_197(float64(val)), nil
+	case DECIMAL:
+		d, err := newDecimal(big.NewInt(val), int(param.prec), int(param.scale))
+		if err != nil {
+			return nil, err
+		}
+		return d.encodeDecimal()
+	case CHAR, VARCHAR2, VARCHAR, CLOB:
+		return Dm_build_1.Dm_build_217(strconv.FormatInt(val, 10), conn.getServerEncoding(), conn), nil
+	case BINARY, VARBINARY, BLOB:
+		return G2DB.ToBinary(val, int(param.prec)), nil
+	case DATE, TIME, DATETIME, DATETIME2:
+		if err := G2DB.checkInt(float64(val)); err != nil {
+			return nil, err
+		}
+		return toDate(val, param.column, *conn)
+	}
+	return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+}
+
+func (G2DB g2db) ToBinary(x int64, prec int) []byte {
+	b := make([]byte, 8)
+	b[7] = byte(x)
+	b[6] = byte(x >> 8)
+	b[5] = byte(x >> 16)
+	b[4] = byte(x >> 24)
+	b[3] = byte(x >> 32)
+	b[2] = byte(x >> 40)
+	b[1] = byte(x >> 48)
+	b[0] = byte(x >> 56)
+
+	if prec > 0 && prec < len(b) {
+		dest := make([]byte, prec)
+		copy(dest, b[len(b)-prec:])
+		return dest
+	}
+	return b
+}
+
+func (G2DB g2db) fromFloat32(val float32, param parameter, conn *DmConnection) ([]byte, error) {
+	switch param.colType {
+	case BOOLEAN, BIT:
+		if val == 0.0 {
+			return Dm_build_1.Dm_build_179(0), nil
+		}
+		return Dm_build_1.Dm_build_179(1), nil
+	case TINYINT:
+		if err := G2DB.checkTinyint(float64(val)); err != nil {
+			return nil, err
+		}
+		return Dm_build_1.Dm_build_179(byte(val)), nil
+	case SMALLINT:
+		if err := G2DB.checkSmallint(float64(val)); err != nil {
+			return nil, err
+		}
+		return Dm_build_1.Dm_build_185(int16(val)), nil
+	case INT:
+		if err := G2DB.checkInt(float64(val)); err != nil {
+			return nil, err
+		}
+		return Dm_build_1.Dm_build_188(int32(val)), nil
+	case BIGINT:
+		if err := G2DB.checkBigint(float64(val)); err != nil {
+			return nil, err
+		}
+		return Dm_build_1.Dm_build_191(int64(val)), nil
+	case REAL:
+		if err := G2DB.checkReal(float64(val)); err != nil {
+			return nil, err
+		}
+		return Dm_build_1.Dm_build_194(val), nil
+	case DOUBLE:
+		return Dm_build_1.Dm_build_197(float64(val)), nil
+	case DECIMAL:
+		d, err := newDecimal(big.NewFloat(float64(val)), int(param.prec), int(param.scale))
+		if err != nil {
+			return nil, err
+		}
+		return d.encodeDecimal()
+	case CHAR, VARCHAR2, VARCHAR, CLOB:
+		return Dm_build_1.Dm_build_217(strconv.FormatFloat(float64(val), 'f', -1, 32), conn.getServerEncoding(), conn), nil
+	}
+	return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+}
+
+func (G2DB g2db) fromFloat64(val float64, param parameter, conn *DmConnection) ([]byte, error) {
+
+	switch param.colType {
+	case BOOLEAN, BIT:
+		if val == 0.0 {
+			return Dm_build_1.Dm_build_179(0), nil
+		}
+		return Dm_build_1.Dm_build_179(1), nil
+
+	case TINYINT:
+		err := G2DB.checkTinyint(val)
+
+		if err != nil {
+			return nil, err
+		}
+
+		return Dm_build_1.Dm_build_179(byte(val)), nil
+	case SMALLINT:
+		err := G2DB.checkSmallint(val)
+
+		if err != nil {
+			return nil, err
+		}
+
+		return Dm_build_1.Dm_build_185(int16(val)), nil
+	case INT:
+		err := G2DB.checkInt(val)
+
+		if err != nil {
+			return nil, err
+		}
+
+		return Dm_build_1.Dm_build_188(int32(val)), nil
+	case BIGINT:
+		err := G2DB.checkBigint(val)
+
+		if err != nil {
+			return nil, err
+		}
+
+		return Dm_build_1.Dm_build_191(int64(val)), nil
+	case REAL:
+		err := G2DB.checkReal(val)
+
+		if err != nil {
+			return nil, err
+		}
+
+		return Dm_build_1.Dm_build_194(float32(val)), nil
+	case DOUBLE:
+		return Dm_build_1.Dm_build_197(float64(val)), nil
+	case DECIMAL:
+		d, err := newDecimal(big.NewFloat(val), int(param.prec), int(param.scale))
+		if err != nil {
+			return nil, err
+		}
+		return d.encodeDecimal()
+	case CHAR, VARCHAR2, VARCHAR, CLOB:
+		return Dm_build_1.Dm_build_217(strconv.FormatFloat(val, 'f', -1, 64), conn.getServerEncoding(), conn), nil
+	}
+	return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+}
+
+func (G2DB g2db) fromBytes(val []byte, param parameter, conn *DmConnection) (interface{}, error) {
+	switch param.colType {
+	case CHAR, VARCHAR2, VARCHAR:
+		return G2DB.toVarchar(val)
+	case CLOB:
+		b, err := G2DB.toVarchar(val)
+		if err != nil {
+			return nil, err
+		}
+		return G2DB.changeOffRowData(param, b, conn.getServerEncoding())
+	case BINARY, VARBINARY:
+		return val, nil
+	case BLOB:
+		return G2DB.bytes2Blob(val, param, conn)
+	case ARRAY, CLASS, PLTYPE_RECORD, SARRAY:
+		if param.typeDescriptor == nil {
+			return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+		}
+		return TypeDataSV.objBlobToBytes(val, param.typeDescriptor)
+	}
+	return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+}
+
+func (G2DB g2db) toVarchar(bsArr []byte) ([]byte, error) {
+	if bsArr == nil || len(bsArr) == 0 {
+		return make([]byte, 0), nil
+	}
+
+	realLen := len(bsArr) * 2
+	bsRet := make([]byte, realLen)
+	for i := 0; i < len(bsArr); i++ {
+		bsTemp, err := G2DB.toChar(bsArr[i])
+		if err != nil {
+			return nil, err
+		}
+
+		bsRet[i*2] = bsTemp[0]
+		bsRet[i*2+1] = bsTemp[1]
+	}
+
+	return bsRet, nil
+}
+
+func (G2DB g2db) toChar(bt byte) ([]byte, error) {
+	bytes := make([]byte, 2)
+	var err error
+
+	bytes[0], err = G2DB.getCharByNumVal((bt >> 4) & 0x0F)
+	if err != nil {
+		return nil, err
+	}
+
+	bytes[1], err = G2DB.getCharByNumVal(bt & 0x0F)
+	if err != nil {
+		return nil, err
+	}
+
+	return bytes, nil
+}
+
+func (G2DB g2db) getCharByNumVal(val byte) (byte, error) {
+	if val >= 0 && val <= 9 {
+		return (byte)(val + '0'), nil
+	}
+
+	if val >= 0x0a && val <= 0x0F {
+		return (byte)(val + 'A' - 0x0a), nil
+	}
+	return 0, ECGO_INVALID_HEX.throw()
+}
+
+func (G2DB g2db) fromString(val string, param parameter, conn *DmConnection) (interface{}, error) {
+	switch param.colType {
+	case BOOLEAN, BIT:
+		ret, err := G2DB.toBool(val)
+		if err != nil {
+			return nil, err
+		}
+
+		if ret {
+			return Dm_build_1.Dm_build_179(byte(1)), nil
+		} else {
+			return Dm_build_1.Dm_build_179(byte(0)), nil
+		}
+
+	case TINYINT, SMALLINT, INT, BIGINT:
+		f, ok := new(big.Float).SetString(val)
+		if !ok {
+			return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+		}
+		if f.Sign() < 0 {
+			f.Sub(f, big.NewFloat(0.5))
+		} else {
+			f.Add(f, big.NewFloat(0.5))
+		}
+		z, _ := f.Int(nil)
+		return G2DB.fromBigInt(z, param, conn)
+	case REAL, DOUBLE, DECIMAL:
+		f, ok := new(big.Float).SetString(val)
+		if ok {
+			return G2DB.fromBigFloat(f, param, conn)
+		} else {
+			return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+		}
+
+	case CHAR, VARCHAR2, VARCHAR:
+		if param.mask == MASK_BFILE && !isValidBFileStr(val) {
+			return nil, ECGO_INVALID_BFILE_STR.throw()
+		}
+		return Dm_build_1.Dm_build_217(val, conn.getServerEncoding(), conn), nil
+	case CLOB:
+		return G2DB.string2Clob(val, param, conn)
+	case BINARY, VARBINARY:
+		return util.StringUtil.HexStringToBytes(val), nil
+	case BLOB:
+		return G2DB.bytes2Blob(util.StringUtil.HexStringToBytes(val), param, conn)
+	case DATE:
+		if conn.FormatDate != "" {
+			dt, err := parse(val, conn.FormatDate, int(conn.OracleDateLanguage))
+			if err != nil {
+				return nil, err
+			}
+
+			return encode(dt, param.column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
+		}
+
+		return encodeByString(val, param.column, *conn)
+	case TIME:
+		if conn.FormatTime != "" {
+			dt, err := parse(val, conn.FormatTime, int(conn.OracleDateLanguage))
+			if err != nil {
+				return nil, err
+			}
+
+			return encode(dt, param.column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
+		}
+
+		return encodeByString(val, param.column, *conn)
+	case DATETIME, DATETIME2:
+		if conn.FormatTimestamp != "" {
+			dt, err := parse(val, conn.FormatTimestamp, int(conn.OracleDateLanguage))
+			if err != nil {
+				return nil, err
+			}
+
+			return encode(dt, param.column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
+		}
+
+		return encodeByString(val, param.column, *conn)
+	case TIME_TZ:
+		dt, err := parse(val, conn.FormatTimeTZ, int(conn.OracleDateLanguage))
+		if err != nil {
+			return nil, err
+		}
+
+		if conn.FormatTimeTZ != "" {
+			return encode(dt, param.column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
+		}
+
+		return encodeByString(val, param.column, *conn)
+	case DATETIME_TZ, DATETIME2_TZ:
+		if conn.FormatTimestampTZ != "" {
+			dt, err := parse(val, conn.FormatTimestampTZ, int(conn.OracleDateLanguage))
+			if err != nil {
+				return nil, err
+			}
+
+			return encode(dt, param.column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
+		}
+
+		return encodeByString(val, param.column, *conn)
+	case INTERVAL_DT:
+		dt, err := NewDmIntervalDTByString(val)
+		if err != nil {
+			return nil, err
+		}
+		return dt.encode(int(param.scale))
+
+	case INTERVAL_YM:
+		ym, err := NewDmIntervalYMByString(val)
+		if err != nil {
+			return nil, err
+		}
+		return ym.encode(int(param.scale))
+	}
+	return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+}
+
+func (G2DB g2db) toBool(str string) (bool, error) {
+	str = strings.TrimSpace(str)
+	if util.StringUtil.Equals(str, "0") {
+		return false, nil
+	} else if util.StringUtil.Equals(str, "1") {
+		return true, nil
+	}
+
+	return strings.ToLower(str) == "true", nil
+}
+
+func (G2DB g2db) fromBigInt(val *big.Int, param parameter, conn *DmConnection) ([]byte, error) {
+	var ret []byte
+	switch param.colType {
+	case BOOLEAN, BIT:
+		if val.Sign() == 0 {
+			ret = Dm_build_1.Dm_build_179(0)
+		} else {
+			ret = Dm_build_1.Dm_build_179(1)
+		}
+	case TINYINT:
+		err := G2DB.checkTinyint(float64(val.Int64()))
+
+		if err != nil {
+			return nil, err
+		}
+
+		ret = Dm_build_1.Dm_build_179(byte(val.Int64()))
+	case SMALLINT:
+		err := G2DB.checkSmallint(float64(val.Int64()))
+
+		if err != nil {
+			return nil, err
+		}
+
+		ret = Dm_build_1.Dm_build_185(int16(val.Int64()))
+	case INT:
+		err := G2DB.checkInt(float64(val.Int64()))
+
+		if err != nil {
+			return nil, err
+		}
+
+		ret = Dm_build_1.Dm_build_188(int32(val.Int64()))
+	case BIGINT:
+		err := G2DB.checkBigint(float64(val.Int64()))
+
+		if err != nil {
+			return nil, err
+		}
+
+		ret = Dm_build_1.Dm_build_191(val.Int64())
+	case REAL:
+		err := G2DB.checkReal(float64(val.Int64()))
+
+		if err != nil {
+			return nil, err
+		}
+
+		ret = Dm_build_1.Dm_build_194(float32(val.Int64()))
+	case DOUBLE:
+		ret = Dm_build_1.Dm_build_197(float64(val.Int64()))
+	case DECIMAL, BINARY, VARBINARY, BLOB:
+		d, err := newDecimal(val, int(param.prec), int(param.scale))
+		if err != nil {
+			return nil, err
+		}
+		ret, err = d.encodeDecimal()
+		if err != nil {
+			return nil, err
+		}
+	case CHAR, VARCHAR2, VARCHAR, CLOB:
+		ret = Dm_build_1.Dm_build_217(val.String(), conn.getServerEncoding(), conn)
+	default:
+		return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+	}
+	return ret, nil
+}
+
+func (G2DB g2db) fromBigFloat(val *big.Float, param parameter, conn *DmConnection) ([]byte, error) {
+	var ret []byte
+	switch param.colType {
+	case BOOLEAN, BIT:
+		if val.Sign() == 0 {
+			ret = Dm_build_1.Dm_build_179(0)
+		} else {
+			ret = Dm_build_1.Dm_build_179(1)
+		}
+	case TINYINT:
+		f, _ := val.Float64()
+
+		err := G2DB.checkTinyint(f)
+
+		if err != nil {
+			return nil, err
+		}
+
+		ret = Dm_build_1.Dm_build_179(byte(f))
+	case SMALLINT:
+		f, _ := val.Float64()
+
+		err := G2DB.checkSmallint(f)
+
+		if err != nil {
+			return nil, err
+		}
+
+		ret = Dm_build_1.Dm_build_185(int16(f))
+	case INT:
+		f, _ := val.Float64()
+
+		err := G2DB.checkInt(f)
+
+		if err != nil {
+			return nil, err
+		}
+
+		ret = Dm_build_1.Dm_build_188(int32(f))
+	case BIGINT:
+		f, _ := val.Float64()
+
+		err := G2DB.checkBigint(f)
+
+		if err != nil {
+			return nil, err
+		}
+
+		ret = Dm_build_1.Dm_build_191(int64(f))
+	case REAL:
+		f, _ := val.Float64()
+
+		err := G2DB.checkReal(f)
+
+		if err != nil {
+			return nil, err
+		}
+
+		ret = Dm_build_1.Dm_build_194(float32(f))
+	case DOUBLE:
+		f, _ := val.Float64()
+		ret = Dm_build_1.Dm_build_197(f)
+	case DECIMAL:
+		d, err := newDecimal(val, int(param.prec), int(param.scale))
+		if err != nil {
+			return nil, err
+		}
+		ret, err = d.encodeDecimal()
+		if err != nil {
+			return nil, err
+		}
+	case CHAR, VARCHAR2, VARCHAR, CLOB:
+		ret = Dm_build_1.Dm_build_217(val.Text('f', int(param.scale)), conn.getServerEncoding(), conn)
+	default:
+		return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+	}
+	return ret, nil
+}
+
+func (G2DB g2db) fromDecimal(val DmDecimal, param parameter, conn *DmConnection) ([]byte, error) {
+	var ret []byte
+	switch param.colType {
+	case BOOLEAN, BIT:
+		if val.Sign() == 0 {
+			ret = Dm_build_1.Dm_build_179(0)
+		} else {
+			ret = Dm_build_1.Dm_build_179(1)
+		}
+	case TINYINT:
+		if err := G2DB.checkTinyint(val); err != nil {
+			return nil, err
+		}
+		ret = Dm_build_1.Dm_build_179(byte(val.ToBigInt().Int64()))
+	case SMALLINT:
+		if err := G2DB.checkSmallint(val); err != nil {
+			return nil, err
+		}
+		ret = Dm_build_1.Dm_build_185(int16(val.ToBigInt().Int64()))
+	case INT:
+		if err := G2DB.checkInt(val); err != nil {
+			return nil, err
+		}
+		ret = Dm_build_1.Dm_build_188(int32(val.ToBigInt().Int64()))
+	case BIGINT:
+		if err := G2DB.checkBigint(val); err != nil {
+			return nil, err
+		}
+		ret = Dm_build_1.Dm_build_191(int64(val.ToBigInt().Int64()))
+	case REAL:
+		if err := G2DB.checkReal(val); err != nil {
+			return nil, err
+		}
+		f, _ := val.ToBigFloat().Float32()
+		ret = Dm_build_1.Dm_build_194(f)
+	case DOUBLE:
+		f, _ := val.ToBigFloat().Float64()
+		ret = Dm_build_1.Dm_build_197(f)
+	case DECIMAL:
+		var err error
+		ret, err = val.encodeDecimal()
+		if err != nil {
+			return nil, err
+		}
+	case CHAR, VARCHAR2, VARCHAR, CLOB:
+		ret = Dm_build_1.Dm_build_217(val.ToBigFloat().Text('f', -1), conn.getServerEncoding(), conn)
+	default:
+		return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+	}
+	return ret, nil
+}
+
+func (G2DB g2db) fromTime(val time.Time, param parameter, conn *DmConnection) ([]byte, error) {
+
+	switch param.colType {
+	case DATE, DATETIME, DATETIME_TZ, TIME, TIME_TZ, DATETIME2, DATETIME2_TZ:
+		return encodeByTime(val, param.column, *conn)
+	case CHAR, VARCHAR2, VARCHAR, CLOB:
+		return Dm_build_1.Dm_build_217(val.Format("2006-01-02 15:04:05.999999999 -07:00"), conn.getServerEncoding(), conn), nil
+	}
+
+	return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+}
+
+func (G2DB g2db) fromDmIntervalDT(val DmIntervalDT, param parameter, conn *DmConnection) ([]byte, error) {
+	switch param.colType {
+	case CHAR, VARCHAR2, VARCHAR, CLOB:
+		return Dm_build_1.Dm_build_217(val.String(), conn.getServerEncoding(), conn), nil
+	case INTERVAL_DT:
+		return val.encode(int(param.scale))
+	default:
+		return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+	}
+}
+
+func (G2DB g2db) fromDmdbIntervalYM(val DmIntervalYM, param parameter, conn *DmConnection) ([]byte, error) {
+
+	switch param.colType {
+	case CHAR, VARCHAR, VARCHAR2, CLOB:
+		return Dm_build_1.Dm_build_217(val.String(), conn.getServerEncoding(), conn), nil
+	case INTERVAL_YM:
+		return val.encode(int(param.scale))
+	default:
+		return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+	}
+}
+
+func (G2DB g2db) fromBlob(val DmBlob, param parameter, conn *DmConnection) (interface{}, error) {
+	var ret interface{}
+	switch param.colType {
+	case BINARY, VARBINARY:
+		len, err := val.GetLength()
+		if err != nil {
+			return nil, err
+		}
+		ret, err = val.getBytes(1, int32(len))
+		if err != nil {
+			return nil, err
+		}
+	case BLOB:
+		var err error
+		ret, err = G2DB.blob2Blob(val, param, conn)
+		if err != nil {
+			return nil, err
+		}
+	case ARRAY, CLASS, PLTYPE_RECORD, SARRAY:
+
+	default:
+		return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+	}
+	return ret, nil
+}
+
+func (G2DB g2db) fromClob(val DmClob, param parameter, conn *DmConnection) (interface{}, error) {
+	var ret interface{}
+	switch param.colType {
+	case CHAR, VARCHAR, VARCHAR2:
+		var len int64
+		var s string
+		var err error
+		len, err = val.GetLength()
+		if err != nil {
+			return nil, err
+		}
+		s, err = val.getSubString(1, int32(len))
+		if err != nil {
+			return nil, err
+		}
+		ret = []byte(s)
+	case CLOB:
+		var err error
+		ret, err = G2DB.clob2Clob(val, param, conn)
+		if err != nil {
+			return nil, err
+		}
+	default:
+		return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+	}
+	return ret, nil
+}
+
+func (G2DB g2db) fromReader(val io.Reader, param parameter, conn *DmConnection) (interface{}, error) {
+	var ret interface{}
+	switch param.colType {
+	case CHAR, VARCHAR2, VARCHAR:
+		var bytesBuf = new(bytes.Buffer)
+		if _, err := bytesBuf.ReadFrom(val); err != nil {
+			return nil, err
+		}
+		return Dm_build_1.Dm_build_217(string(bytesBuf.Bytes()), conn.getServerEncoding(), conn), nil
+	case BINARY, VARBINARY:
+		var bytesBuf = new(bytes.Buffer)
+		if _, err := bytesBuf.ReadFrom(val); err != nil {
+			return nil, err
+		}
+		return util.StringUtil.HexStringToBytes(string(bytesBuf.Bytes())), nil
+	case BLOB, CLOB:
+		var binder = newOffRowReaderBinder(val, conn.getServerEncoding())
+		if binder.offRow {
+			ret = binder
+		} else {
+			ret = binder.readAll()
+		}
+	default:
+		return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+	}
+	return ret, nil
+}
+
+func (G2DB g2db) string2Clob(val string, param parameter, conn *DmConnection) (interface{}, error) {
+	return G2DB.changeOffRowData(param, Dm_build_1.Dm_build_217(val, conn.getServerEncoding(), conn), conn.getServerEncoding())
+}
+
+func (G2DB g2db) bytes2Blob(val []byte, param parameter, conn *DmConnection) (interface{}, error) {
+	return G2DB.changeOffRowData(param, val, conn.getServerEncoding())
+}
+
+func (G2DB g2db) clob2Clob(val DmClob, param parameter, conn *DmConnection) (interface{}, error) {
+	var clobLen int64
+	var err error
+	if clobLen, err = val.GetLength(); err != nil {
+		return nil, err
+	}
+	if G2DB.isOffRow(param.colType, clobLen) {
+		return newOffRowClobBinder(val, conn.getServerEncoding()), nil
+	} else {
+		var length int64
+		var str string
+		if length, err = val.GetLength(); err != nil {
+			return nil, err
+		}
+		if str, err = val.getSubString(1, int32(length)); err != nil {
+			return nil, err
+		}
+		return Dm_build_1.Dm_build_217(str, conn.getServerEncoding(), conn), nil
+	}
+}
+
+func (G2DB g2db) blob2Blob(val DmBlob, param parameter, conn *DmConnection) (interface{}, error) {
+	var clobLen int64
+	var err error
+	if clobLen, err = val.GetLength(); err != nil {
+		return nil, err
+	}
+	if G2DB.isOffRow(param.colType, clobLen) {
+		return newOffRowBlobBinder(val, conn.getServerEncoding()), nil
+	} else {
+		var length int64
+		if length, err = val.GetLength(); err != nil {
+			return nil, err
+		}
+		return val.getBytes(1, int32(length))
+	}
+}
+
+func (G2DB g2db) changeOffRowData(paramDesc parameter, paramData []byte, encoding string) (interface{}, error) {
+	if G2DB.isOffRow(paramDesc.colType, int64(len(paramData))) {
+		return newOffRowBytesBinder(paramData, encoding), nil
+	} else {
+		return paramData, nil
+	}
+}
+
+func (G2DB g2db) isOffRow(dtype int32, length int64) bool {
+	return (dtype == BLOB || dtype == CLOB) && length > Dm_build_1086
+}
+
+func (G2DB g2db) fromObject(mem interface{}, param parameter, conn *DmConnection) ([]byte, error) {
+	switch v := mem.(type) {
+	case bool:
+		return G2DB.fromBool(v, param, conn)
+	case string:
+		val, err := G2DB.fromString(v, param, conn)
+		if err != nil {
+			return nil, err
+		}
+		return val.([]byte), err
+	case byte:
+		return G2DB.fromInt64(int64(v), param, conn)
+	case int:
+		return G2DB.fromInt64(int64(v), param, conn)
+	case int16:
+		return G2DB.fromInt64(int64(v), param, conn)
+	case int32:
+		return G2DB.fromInt64(int64(v), param, conn)
+	case int64:
+		return G2DB.fromInt64(v, param, conn)
+	case float32:
+		return G2DB.fromFloat64(float64(v), param, conn)
+	case float64:
+		return G2DB.fromFloat64(v, param, conn)
+	case time.Time:
+		return G2DB.fromTime(v, param, conn)
+	case DmDecimal:
+		return G2DB.fromDecimal(v, param, conn)
+	case DmIntervalDT:
+		return G2DB.fromDmIntervalDT(v, param, conn)
+	case DmIntervalYM:
+		return G2DB.fromDmdbIntervalYM(v, param, conn)
+	case DmBlob:
+		length, _ := v.GetLength()
+		return v.getBytes(1, int32(length))
+	case DmClob:
+		length, _ := v.GetLength()
+		str, err := v.getSubString(1, int32(length))
+		if err != nil {
+			return nil, err
+		}
+		return Dm_build_1.Dm_build_217(str, conn.getServerEncoding(), conn), nil
+	default:
+		return nil, ECGO_UNSUPPORTED_TYPE.throw()
+	}
+
+}
+
+func (G2DB g2db) toInt32(val int32) []byte {
+	bytes := make([]byte, 4)
+	Dm_build_1.Dm_build_17(bytes, 0, val)
+	return bytes
+}
+
+func (G2DB g2db) toInt64(val int64) []byte {
+	bytes := make([]byte, 8)
+	Dm_build_1.Dm_build_22(bytes, 0, val)
+	return bytes
+}
+
+func (G2DB g2db) toFloat32(val float32) []byte {
+	bytes := make([]byte, 4)
+	Dm_build_1.Dm_build_27(bytes, 0, val)
+	return bytes
+}
+
+func (G2DB g2db) toFloat64(val float64) []byte {
+	bytes := make([]byte, 8)
+	Dm_build_1.Dm_build_32(bytes, 0, val)
+	return bytes
+}
+
+func (G2DB g2db) toDecimal(val string, prec int, scale int) ([]byte, error) {
+	d, err := decodeDecimal([]byte(val), prec, scale)
+	if err != nil {
+		return nil, err
+	}
+	return d.encodeDecimal()
+}
+
+func (G2DB g2db) fromArray(x *DmArray, param parameter, connection *DmConnection) (interface{}, error) {
+	var ret interface{}
+	var err error
+	switch param.colType {
+	case SARRAY:
+		ret, err = TypeDataSV.sarrayToBytes(x, param.typeDescriptor)
+	case CLASS, ARRAY:
+		ret, err = TypeDataSV.arrayToBytes(x, param.typeDescriptor)
+	case BLOB:
+		ret, err = TypeDataSV.toBytesFromDmArray(x, param.typeDescriptor)
+		if err == nil {
+			ret, err = G2DB.bytes2Blob(ret.([]byte), param, connection)
+		}
+	default:
+		err = ECGO_DATA_CONVERTION_ERROR.throw()
+	}
+	return ret, err
+}
+
+func (G2DB g2db) fromStruct(x *DmStruct, param parameter, connection *DmConnection) (interface{}, error) {
+	var ret interface{}
+	var err error
+	switch param.colType {
+	case CLASS:
+		ret, err = TypeDataSV.structToBytes(x, param.typeDescriptor)
+	case PLTYPE_RECORD:
+		ret, err = TypeDataSV.recordToBytes(x, param.typeDescriptor)
+	case BLOB:
+		ret, err = TypeDataSV.toBytesFromDmStruct(x, param.typeDescriptor)
+		if err == nil {
+			ret, err = G2DB.bytes2Blob(ret.([]byte), param, connection)
+		}
+
+	default:
+		err = ECGO_DATA_CONVERTION_ERROR.throw()
+	}
+	return ret, err
+}
+
+func isValidBFileStr(s string) bool {
+	strs := strings.Split(strings.TrimSpace(s), ":")
+	if len(strs) != 2 {
+		return false
+	}
+	if len(strs[0]) > Dm_build_1014 || len(strs[1]) > Dm_build_1015 {
+		return false
+	}
+	return true
+}

+ 137 - 0
zn.go

@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+const (
+	LOB_FLAG_BYTE = 0
+	LOB_FLAG_CHAR = 1
+
+	LOB_IN_ROW  = 0x1
+	LOB_OFF_ROW = 0x2
+
+	NBLOB_HEAD_IN_ROW_FLAG = 0
+	NBLOB_HEAD_BLOBID      = NBLOB_HEAD_IN_ROW_FLAG + BYTE_SIZE
+	NBLOB_HEAD_BLOB_LEN    = NBLOB_HEAD_BLOBID + DDWORD_SIZE
+
+	NBLOB_HEAD_OUTROW_GROUPID = NBLOB_HEAD_BLOB_LEN + ULINT_SIZE
+	NBLOB_HEAD_OUTROW_FILEID  = NBLOB_HEAD_OUTROW_GROUPID + USINT_SIZE
+	NBLOB_HEAD_OUTROW_PAGENO  = NBLOB_HEAD_OUTROW_FILEID + USINT_SIZE
+
+	NBLOB_EX_HEAD_TABLE_ID   = NBLOB_HEAD_OUTROW_PAGENO + ULINT_SIZE
+	NBLOB_EX_HEAD_COL_ID     = NBLOB_EX_HEAD_TABLE_ID + ULINT_SIZE
+	NBLOB_EX_HEAD_ROW_ID     = NBLOB_EX_HEAD_COL_ID + USINT_SIZE
+	NBLOB_EX_HEAD_FPA_GRPID  = NBLOB_EX_HEAD_ROW_ID + LINT64_SIZE
+	NBLOB_EX_HEAD_FPA_FILEID = NBLOB_EX_HEAD_FPA_GRPID + USINT_SIZE
+	NBLOB_EX_HEAD_FPA_PAGENO = NBLOB_EX_HEAD_FPA_FILEID + USINT_SIZE
+	NBLOB_EX_HEAD_SIZE       = NBLOB_EX_HEAD_FPA_PAGENO + ULINT_SIZE
+
+	NBLOB_OUTROW_HEAD_SIZE = NBLOB_HEAD_OUTROW_PAGENO + ULINT_SIZE
+
+	NBLOB_INROW_HEAD_SIZE = NBLOB_HEAD_BLOB_LEN + ULINT_SIZE
+)
+
+type lob struct {
+	blobId int64
+	inRow  bool
+
+	groupId   int16
+	fileId    int16
+	pageNo    int32
+	tabId     int32
+	colId     int16
+	rowId     int64
+	exGroupId int16
+	exFileId  int16
+	exPageNo  int32
+
+	curFileId     int16
+	curPageNo     int32
+	curPageOffset int16
+	totalOffset   int32
+	readOver      bool
+
+	connection       *DmConnection
+	local            bool
+	updateable       bool
+	lobFlag          int8
+	length           int64
+	compatibleOracle bool
+	fetchAll         bool
+	freed            bool
+	modify           bool
+
+	Valid bool
+}
+
+func (lob *lob) GetLength() (int64, error) {
+	var err error
+	if err = lob.checkValid(); err != nil {
+		return -1, err
+	}
+	if err = lob.checkFreed(); err != nil {
+		return -1, err
+	}
+	if lob.length == -1 {
+
+		if lob.length, err = lob.connection.Access.dm_build_856(lob); err != nil {
+			return -1, err
+		}
+	}
+	return lob.length, nil
+}
+
+func (lob *lob) resetCurrentInfo() {
+	lob.curFileId = lob.fileId
+	lob.curPageNo = lob.pageNo
+	lob.totalOffset = 0
+	lob.curPageOffset = 0
+}
+
+func (lob *lob) getLengthFromHead(head []byte) int64 {
+	return int64(Dm_build_1.Dm_build_103(head, NBLOB_HEAD_BLOB_LEN))
+}
+
+func (lob *lob) canOptimized(connection *DmConnection) bool {
+	return !(lob.inRow || lob.fetchAll || lob.local || connection != lob.connection)
+}
+
+func (lob *lob) buildCtlData() (bytes []byte) {
+	if lob.connection.NewLobFlag {
+		bytes = make([]byte, NBLOB_EX_HEAD_SIZE, NBLOB_EX_HEAD_SIZE)
+	} else {
+		bytes = make([]byte, NBLOB_OUTROW_HEAD_SIZE, NBLOB_OUTROW_HEAD_SIZE)
+	}
+	Dm_build_1.Dm_build_2(bytes, NBLOB_HEAD_IN_ROW_FLAG, LOB_OFF_ROW)
+	Dm_build_1.Dm_build_22(bytes, NBLOB_HEAD_BLOBID, lob.blobId)
+	Dm_build_1.Dm_build_17(bytes, NBLOB_HEAD_BLOB_LEN, -1)
+
+	Dm_build_1.Dm_build_12(bytes, NBLOB_HEAD_OUTROW_GROUPID, lob.groupId)
+	Dm_build_1.Dm_build_12(bytes, NBLOB_HEAD_OUTROW_FILEID, lob.fileId)
+	Dm_build_1.Dm_build_17(bytes, NBLOB_HEAD_OUTROW_PAGENO, lob.pageNo)
+
+	if lob.connection.NewLobFlag {
+		Dm_build_1.Dm_build_17(bytes, NBLOB_EX_HEAD_TABLE_ID, lob.tabId)
+		Dm_build_1.Dm_build_12(bytes, NBLOB_EX_HEAD_COL_ID, lob.colId)
+		Dm_build_1.Dm_build_22(bytes, NBLOB_EX_HEAD_ROW_ID, lob.rowId)
+		Dm_build_1.Dm_build_12(bytes, NBLOB_EX_HEAD_FPA_GRPID, lob.exGroupId)
+		Dm_build_1.Dm_build_12(bytes, NBLOB_EX_HEAD_FPA_FILEID, lob.exFileId)
+		Dm_build_1.Dm_build_17(bytes, NBLOB_EX_HEAD_FPA_PAGENO, lob.exPageNo)
+	}
+	return
+}
+
+func (lob *lob) checkFreed() (err error) {
+	if lob.freed {
+		err = ECGO_LOB_FREED.throw()
+	}
+	return
+}
+
+func (lob *lob) checkValid() error {
+	if !lob.Valid {
+		return ECGO_IS_NULL.throw()
+	}
+	return nil
+}

+ 19 - 0
zo.go

@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package dm
+
+const (
+	ParamDataEnum_Null = 0
+	/**
+	 * 只有大字段才有行内数据、行外数据的概念
+	 */
+	ParamDataEnum_OFF_ROW = 1
+)
+
+// JDBC中的Data
+type lobCtl struct {
+	value []byte
+}

+ 124 - 0
zp.go

@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"fmt"
+	"os"
+	"strconv"
+	"strings"
+	"time"
+
+	"gitee.com/chunanyong/dm/util"
+)
+
+const (
+	MAX_FILE_SIZE = 100 * 1024 * 1024
+	FLUSH_SIZE    = 32 * 1024
+)
+
+type goRun interface {
+	doRun()
+}
+
+type logWriter struct {
+	flushQueue chan []byte
+	date       string
+	logFile    *os.File
+	flushFreq  int
+	filePath   string
+	filePrefix string
+	buffer     *Dm_build_283
+}
+
+func (lw *logWriter) doRun() {
+	defer func() {
+		lw.beforeExit()
+		lw.closeCurrentFile()
+	}()
+
+	i := 0
+	for {
+		var ibytes []byte
+
+		select {
+		case ibytes = <-lw.flushQueue:
+			if LogLevel != LOG_OFF {
+				if i == LogFlushQueueSize {
+					lw.doFlush(lw.buffer)
+					i = 0
+				} else {
+					lw.buffer.Dm_build_309(ibytes, 0, len(ibytes))
+					i++
+				}
+			}
+		case <-time.After(time.Duration(LogFlushFreq) * time.Millisecond):
+			if LogLevel != LOG_OFF && lw.buffer.Dm_build_288() > 0 {
+				lw.doFlush(lw.buffer)
+				i = 0
+			}
+
+		}
+
+	}
+}
+
+func (lw *logWriter) doFlush(buffer *Dm_build_283) {
+	if lw.needCreateNewFile() {
+		lw.closeCurrentFile()
+		lw.logFile = lw.createNewFile()
+	}
+	if lw.logFile != nil {
+		buffer.Dm_build_303(lw.logFile, buffer.Dm_build_288())
+	}
+}
+func (lw *logWriter) closeCurrentFile() {
+	if lw.logFile != nil {
+		lw.logFile.Close()
+		lw.logFile = nil
+	}
+}
+func (lw *logWriter) createNewFile() *os.File {
+	lw.date = time.Now().Format("2006-01-02")
+	fileName := lw.filePrefix + "_" + lw.date + "_" + strconv.Itoa(time.Now().Nanosecond()) + ".log"
+	lw.filePath = LogDir
+	if len(lw.filePath) > 0 {
+		if _, err := os.Stat(lw.filePath); err != nil {
+			os.MkdirAll(lw.filePath, 0755)
+		}
+		if _, err := os.Stat(lw.filePath + fileName); err != nil {
+			logFile, err := os.Create(lw.filePath + fileName)
+			if err != nil {
+				fmt.Println(err)
+				return nil
+			}
+			return logFile
+		}
+	}
+	return nil
+}
+func (lw *logWriter) needCreateNewFile() bool {
+	now := time.Now().Format("2006-01-02")
+	fileInfo, err := lw.logFile.Stat()
+	return now != lw.date || err != nil || lw.logFile == nil || fileInfo.Size() > int64(MAX_FILE_SIZE)
+}
+func (lw *logWriter) beforeExit() {
+	close(lw.flushQueue)
+	var ibytes []byte
+	for ibytes = <-lw.flushQueue; ibytes != nil; ibytes = <-lw.flushQueue {
+		lw.buffer.Dm_build_309(ibytes, 0, len(ibytes))
+		if lw.buffer.Dm_build_288() >= LogBufferSize {
+			lw.doFlush(lw.buffer)
+		}
+	}
+	if lw.buffer.Dm_build_288() > 0 {
+		lw.doFlush(lw.buffer)
+	}
+}
+
+func (lw *logWriter) WriteLine(msg string) {
+	var b = []byte(strings.TrimSpace(msg) + util.LINE_SEPARATOR)
+	lw.flushQueue <- b
+}

+ 2930 - 0
zq.go

@@ -0,0 +1,2930 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"fmt"
+	"math"
+	"os"
+	"strconv"
+	"strings"
+
+	"gitee.com/chunanyong/dm/util"
+)
+
+const (
+	Dm_build_962 = "7.6.0.0"
+
+	Dm_build_963 = "7.0.0.9"
+
+	Dm_build_964 = "8.0.0.73"
+
+	Dm_build_965 = "7.1.2.128"
+
+	Dm_build_966 = "7.1.5.144"
+
+	Dm_build_967 = "7.1.6.123"
+
+	Dm_build_968 = 1
+
+	Dm_build_969 = 2
+
+	Dm_build_970 = 3
+
+	Dm_build_971 = 4
+
+	Dm_build_972 = 5
+
+	Dm_build_973 = 6
+
+	Dm_build_974 = 8
+
+	Dm_build_975 = Dm_build_974
+
+	Dm_build_976 = 32768 - 128
+
+	Dm_build_977 = 0x20000000
+
+	Dm_build_978 int16 = 1
+
+	Dm_build_979 int16 = 2
+
+	Dm_build_980 int16 = 3
+
+	Dm_build_981 int16 = 4
+
+	Dm_build_982 int16 = 5
+
+	Dm_build_983 int16 = 6
+
+	Dm_build_984 int16 = 7
+
+	Dm_build_985 int16 = 8
+
+	Dm_build_986 int16 = 9
+
+	Dm_build_987 int16 = 13
+
+	Dm_build_988 int16 = 14
+
+	Dm_build_989 int16 = 15
+
+	Dm_build_990 int16 = 17
+
+	Dm_build_991 int16 = 21
+
+	Dm_build_992 int16 = 24
+
+	Dm_build_993 int16 = 27
+
+	Dm_build_994 int16 = 29
+
+	Dm_build_995 int16 = 30
+
+	Dm_build_996 int16 = 31
+
+	Dm_build_997 int16 = 32
+
+	Dm_build_998 int16 = 44
+
+	Dm_build_999 int16 = 52
+
+	Dm_build_1000 int16 = 60
+
+	Dm_build_1001 int16 = 71
+
+	Dm_build_1002 int16 = 90
+
+	Dm_build_1003 int16 = 91
+
+	Dm_build_1004 int16 = 200
+
+	Dm_build_1005 = 64
+
+	Dm_build_1006 = 20
+
+	Dm_build_1007 = 0
+
+	Dm_build_1008 = 4
+
+	Dm_build_1009 = 6
+
+	Dm_build_1010 = 10
+
+	Dm_build_1011 = 14
+
+	Dm_build_1012 = 18
+
+	Dm_build_1013 = 19
+
+	Dm_build_1014 = 128
+
+	Dm_build_1015 = 256
+
+	Dm_build_1016 int32 = 2
+
+	Dm_build_1017 int32 = 5
+
+	Dm_build_1018 = -1
+
+	Dm_build_1019 int32 = 0xFF00
+
+	Dm_build_1020 int32 = 0xFFFE - 3
+
+	Dm_build_1021 int32 = 0xFFFE - 4
+
+	Dm_build_1022 int32 = 0xFFFE
+
+	Dm_build_1023 int32 = 0xFFFF
+
+	Dm_build_1024 int32 = 0x80
+
+	Dm_build_1025 byte = 0x60
+
+	Dm_build_1026 uint16 = uint16(Dm_build_1022)
+
+	Dm_build_1027 uint16 = uint16(Dm_build_1023)
+
+	Dm_build_1028 int16 = 0x00
+
+	Dm_build_1029 int16 = 0x03
+
+	Dm_build_1030 int32 = 0x80
+
+	Dm_build_1031 byte = 0
+
+	Dm_build_1032 byte = 1
+
+	Dm_build_1033 byte = 2
+
+	Dm_build_1034 byte = 3
+
+	Dm_build_1035 byte = 4
+
+	Dm_build_1036 byte = Dm_build_1031
+
+	Dm_build_1037 int = 10
+
+	Dm_build_1038 int32 = 32
+
+	Dm_build_1039 int32 = 65536
+
+	Dm_build_1040 byte = 0
+
+	Dm_build_1041 byte = 1
+
+	Dm_build_1042 int32 = 0x00000000
+
+	Dm_build_1043 int32 = 0x00000020
+
+	Dm_build_1044 int32 = 0x00000040
+
+	Dm_build_1045 int32 = 0x00000FFF
+
+	Dm_build_1046 int32 = 0
+
+	Dm_build_1047 int32 = 1
+
+	Dm_build_1048 int32 = 2
+
+	Dm_build_1049 int32 = 3
+
+	Dm_build_1050 = 8192
+
+	Dm_build_1051 = 1
+
+	Dm_build_1052 = 2
+
+	Dm_build_1053 = 0
+
+	Dm_build_1054 = 0
+
+	Dm_build_1055 = 1
+
+	Dm_build_1056 = -1
+
+	Dm_build_1057 int16 = 0
+
+	Dm_build_1058 int16 = 1
+
+	Dm_build_1059 int16 = 2
+
+	Dm_build_1060 int16 = 3
+
+	Dm_build_1061 int16 = 4
+
+	Dm_build_1062 int16 = 127
+
+	Dm_build_1063 int16 = Dm_build_1062 + 20
+
+	Dm_build_1064 int16 = Dm_build_1062 + 21
+
+	Dm_build_1065 int16 = Dm_build_1062 + 22
+
+	Dm_build_1066 int16 = Dm_build_1062 + 24
+
+	Dm_build_1067 int16 = Dm_build_1062 + 25
+
+	Dm_build_1068 int16 = Dm_build_1062 + 26
+
+	Dm_build_1069 int16 = Dm_build_1062 + 30
+
+	Dm_build_1070 int16 = Dm_build_1062 + 31
+
+	Dm_build_1071 int16 = Dm_build_1062 + 32
+
+	Dm_build_1072 int16 = Dm_build_1062 + 33
+
+	Dm_build_1073 int16 = Dm_build_1062 + 35
+
+	Dm_build_1074 int16 = Dm_build_1062 + 38
+
+	Dm_build_1075 int16 = Dm_build_1062 + 39
+
+	Dm_build_1076 int16 = Dm_build_1062 + 51
+
+	Dm_build_1077 int16 = Dm_build_1062 + 71
+
+	Dm_build_1078 int16 = Dm_build_1062 + 124
+
+	Dm_build_1079 int16 = Dm_build_1062 + 125
+
+	Dm_build_1080 int16 = Dm_build_1062 + 126
+
+	Dm_build_1081 int16 = Dm_build_1062 + 127
+
+	Dm_build_1082 int16 = Dm_build_1062 + 128
+
+	Dm_build_1083 int16 = Dm_build_1062 + 129
+
+	Dm_build_1084 byte = 0
+
+	Dm_build_1085 byte = 2
+
+	Dm_build_1086 = 2048
+
+	Dm_build_1087 = -1
+
+	Dm_build_1088 = 0
+
+	Dm_build_1089 = 16000
+
+	Dm_build_1090 = 32000
+
+	Dm_build_1091 = 0x00000000
+
+	Dm_build_1092 = 0x00000020
+
+	Dm_build_1093 = 0x00000040
+
+	Dm_build_1094 = 0x00000FFF
+
+	Dm_build_1095 = 4
+)
+
+var Dm_build_1096 = [8][256]uint32{
+
+	{0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535,
+		0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b,
+		0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148,
+		0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+		0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63,
+		0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1,
+		0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6,
+		0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac,
+		0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+		0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87,
+		0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc,
+		0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2,
+		0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97,
+		0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+		0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea,
+		0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158,
+		0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d,
+		0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73,
+		0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+		0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e,
+		0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b,
+		0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739,
+		0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e,
+		0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+		0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671,
+		0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f,
+		0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4,
+		0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda,
+		0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+		0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795,
+		0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92,
+		0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0,
+		0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785,
+		0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+		0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8,
+		0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6,
+		0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3,
+		0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661,
+		0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+		0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c,
+		0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729,
+		0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37,
+		0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d},
+
+	{0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504, 0x7d77f445, 0x565aa786,
+		0x4f4196c7, 0xc8d98a08, 0xd1c2bb49, 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c,
+		0xb5ae7e4d, 0x9e832d8e, 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3,
+		0x61ef4192, 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859,
+		0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c, 0xd4413fdf,
+		0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620, 0xbea97761, 0xf1e8e1a6,
+		0xe8f3d0e7, 0xc3de8324, 0xdac5b265, 0x5d5daeaa, 0x44469feb, 0x6f6bcc28,
+		0x7670fd69, 0x39316bae, 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3,
+		0xc65d07b2, 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175,
+		0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38, 0x73f379ff,
+		0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05, 0xe9627e44, 0xc24f2d87,
+		0xdb541cc6, 0x94158a01, 0x8d0ebb40, 0xa623e883, 0xbf38d9c2, 0x38a0c50d,
+		0x21bbf44c, 0x0a96a78f, 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b,
+		0x77e153ca, 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850,
+		0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d, 0x4054b5de,
+		0x594f849f, 0x160e1258, 0x0f152319, 0x243870da, 0x3d23419b, 0x65fd6ba7,
+		0x7ce65ae6, 0x57cb0925, 0x4ed03864, 0x0191aea3, 0x188a9fe2, 0x33a7cc21,
+		0x2abcfd60, 0xad24e1af, 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab,
+		0xd05315ea, 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74,
+		0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, 0xe7e6f3fe,
+		0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa, 0x9a9107bb, 0xb1bc5478,
+		0xa8a76539, 0x3b83984b, 0x2298a90a, 0x09b5fac9, 0x10aecb88, 0x5fef5d4f,
+		0x46f46c0e, 0x6dd93fcd, 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1,
+		0xd8774180, 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a,
+		0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f, 0x271b2d9c,
+		0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290, 0x92b553d1, 0xddf4c516,
+		0xc4eff457, 0xefc2a794, 0xf6d996d5, 0xae07bce9, 0xb71c8da8, 0x9c31de6b,
+		0x852aef2a, 0xca6b79ed, 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1,
+		0x7fc507a0, 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167,
+		0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, 0x80a96bbc,
+		0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0, 0x350715f1, 0x1e2a4632,
+		0x07317773, 0x4870e1b4, 0x516bd0f5, 0x7a468336, 0x635db277, 0xcbfad74e,
+		0xd2e1e60f, 0xf9ccb5cc, 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8,
+		0x84bb4189, 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842,
+		0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e, 0xb30ea79d,
+		0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299, 0xce7953d8, 0x49e14f17,
+		0x50fa7e56, 0x7bd72d95, 0x62cc1cd4, 0x2d8d8a13, 0x3496bb52, 0x1fbbe891,
+		0x06a0d9d0, 0x5e7ef3ec, 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8,
+		0x230907a9, 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66,
+		0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23, 0x14bce1bd,
+		0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9, 0x69cb15f8, 0x42e6463b,
+		0x5bfd777a, 0xdc656bb5, 0xc57e5af4, 0xee530937, 0xf7483876, 0xb809aeb1,
+		0xa1129ff0, 0x8a3fcc33, 0x9324fd72},
+
+	{0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc, 0x06cbc2eb, 0x048d7cb2,
+		0x054f1685, 0x0e1351b8, 0x0fd13b8f, 0x0d9785d6, 0x0c55efe1, 0x091af964,
+		0x08d89353, 0x0a9e2d0a, 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e,
+		0x1e601d29, 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8,
+		0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023, 0x16b88e7a,
+		0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e, 0x3a0bf8b9, 0x3f44ee3c,
+		0x3e86840b, 0x3cc03a52, 0x3d025065, 0x365e1758, 0x379c7d6f, 0x35dac336,
+		0x3418a901, 0x3157bf84, 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590,
+		0x25a98fa7, 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922,
+		0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71, 0x2d711cf4,
+		0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0, 0x7158e7f7, 0x731e59ae,
+		0x72dc3399, 0x7793251c, 0x76514f2b, 0x7417f172, 0x75d59b45, 0x7e89dc78,
+		0x7f4bb64f, 0x7d0d0816, 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca,
+		0x7bc6cafd, 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c,
+		0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f, 0x612bab66,
+		0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba, 0x67e0698d, 0x48d7cb20,
+		0x4915a117, 0x4b531f4e, 0x4a917579, 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792,
+		0x4d98dda5, 0x46c49a98, 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244,
+		0x400f5873, 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e,
+		0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, 0x5ae239e8,
+		0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134, 0x5c29fb03, 0x5e6f455a,
+		0x5fad2f6d, 0xe1351b80, 0xe0f771b7, 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c,
+		0xe7fed96b, 0xe5b86732, 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56,
+		0xed60f461, 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0,
+		0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b, 0xf99ec442,
+		0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26, 0xf1465711, 0xf4094194,
+		0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, 0xd9785d60, 0xd8ba3757, 0xdafc890e,
+		0xdb3ee339, 0xde71f5bc, 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8,
+		0xd6a966ef, 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a,
+		0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049, 0xc25756cc,
+		0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8, 0xca8fc59f, 0xc8c97bc6,
+		0xc90b11f1, 0xcc440774, 0xcd866d43, 0xcfc0d31a, 0xce02b92d, 0x91af9640,
+		0x906dfc77, 0x922b422e, 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2,
+		0x94e080c5, 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24,
+		0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07, 0x8e0de15e,
+		0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982, 0x88c623b5, 0x839a6488,
+		0x82580ebf, 0x801eb0e6, 0x81dcdad1, 0x8493cc54, 0x8551a663, 0x8717183a,
+		0x86d5720d, 0xa9e2d0a0, 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c,
+		0xaf29124b, 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576,
+		0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, 0xb5c473d0,
+		0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c, 0xb30fb13b, 0xb1490f62,
+		0xb08b6555, 0xbbd72268, 0xba15485f, 0xb853f606, 0xb9919c31, 0xbcde8ab4,
+		0xbd1ce083, 0xbf5a5eda, 0xbe9834ed},
+
+	{0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757, 0x37def032, 0x256b5fdc,
+		0x9dd738b9, 0xc5b428ef, 0x7d084f8a, 0x6fbde064, 0xd7018701, 0x4ad6bfb8,
+		0xf26ad8dd, 0xe0df7733, 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14,
+		0x42acf871, 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70,
+		0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42, 0xb0c620ac,
+		0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5, 0xb28700d0, 0x2f503869,
+		0x97ec5f0c, 0x8559f0e2, 0x3de59787, 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a,
+		0x7733283f, 0xeae41086, 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1,
+		0x48979fc4, 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d,
+		0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, 0xbafd4719,
+		0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d, 0x23a83f58, 0x311d90b6,
+		0x89a1f7d3, 0x1476cf6a, 0xaccaa80f, 0xbe7f07e1, 0x06c36084, 0x5ea070d2,
+		0xe61c17b7, 0xf4a9b859, 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e,
+		0xc377486b, 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5,
+		0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028, 0xa4b0efc6,
+		0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891, 0x936e1ff4, 0x3b26f703,
+		0x839a9066, 0x912f3f88, 0x299358ed, 0xb4446054, 0x0cf80731, 0x1e4da8df,
+		0xa6f1cfba, 0xfe92dfec, 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb,
+		0xc94c2fde, 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817,
+		0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, 0xae8b8873,
+		0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24, 0x99557841, 0x8be0d7af,
+		0x335cb0ca, 0xed59b63b, 0x55e5d15e, 0x47507eb0, 0xffec19d5, 0x623b216c,
+		0xda874609, 0xc832e9e7, 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f,
+		0x3a58313a, 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4,
+		0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196, 0x982bbe78,
+		0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, 0x6a4166a5, 0xf7965e1c,
+		0x4f2a3979, 0x5d9f9697, 0xe523f1f2, 0x4d6b1905, 0xf5d77e60, 0xe762d18e,
+		0x5fdeb6eb, 0xc2098e52, 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea,
+		0x3063568f, 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36,
+		0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174, 0x9210d9cd,
+		0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675, 0x607a0110, 0x72cfaefe,
+		0xca73c99b, 0x57a4f122, 0xef189647, 0xfdad39a9, 0x45115ecc, 0x764dee06,
+		0xcef18963, 0xdc44268d, 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da,
+		0xeb9ad6bf, 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be,
+		0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc, 0x8c5d7112,
+		0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645, 0xbb838120, 0xe3e09176,
+		0x5b5cf613, 0x49e959fd, 0xf1553e98, 0x6c820621, 0xd43e6144, 0xc68bceaa,
+		0x7e37a9cf, 0xd67f4138, 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f,
+		0xe1a1b10a, 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c,
+		0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e, 0x866616a7,
+		0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0, 0xb1b8e695, 0xa30d497b,
+		0x1bb12e1e, 0x43d23e48, 0xfb6e592d, 0xe9dbf6c3, 0x516791a6, 0xccb0a91f,
+		0x740cce7a, 0x66b96194, 0xde0506f1},
+
+	{0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0, 0xc8e08f70, 0x8f40f5a0,
+		0xb220dc10, 0x30704bc1, 0x0d106271, 0x4ab018a1, 0x77d03111, 0xc5f0ed01,
+		0xf890c4b1, 0xbf30be61, 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2,
+		0x2740ed52, 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43,
+		0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333, 0xdfd029e3,
+		0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64, 0x866155d4, 0x344189c4,
+		0x0921a074, 0x4e81daa4, 0x73e1f314, 0xf1b164c5, 0xccd14d75, 0x8b7137a5,
+		0xb6111e15, 0x0431c205, 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886,
+		0x9c419136, 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26,
+		0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997, 0x64d15587,
+		0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849, 0x659371f9, 0x22330b29,
+		0x1f532299, 0xad73fe89, 0x9013d739, 0xd7b3ade9, 0xead38459, 0x68831388,
+		0x55e33a38, 0x124340e8, 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628,
+		0xdaa3cf98, 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b,
+		0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba, 0x72a3d76a,
+		0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa, 0xba43581a, 0x9932774d,
+		0xa4525efd, 0xe3f2242d, 0xde920d9d, 0x6cb2d18d, 0x51d2f83d, 0x167282ed,
+		0x2b12ab5d, 0xa9423c8c, 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c,
+		0x61a2b3fc, 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af,
+		0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf, 0xc9a2ab0e,
+		0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce, 0x0142247e, 0x46e25eae,
+		0x7b82771e, 0xb1e6b092, 0x8c869922, 0xcb26e3f2, 0xf646ca42, 0x44661652,
+		0x79063fe2, 0x3ea64532, 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833,
+		0xc6368183, 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710,
+		0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860, 0x5e46d2b0,
+		0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1, 0xa6d61601, 0x14f6ca11,
+		0x2996e3a1, 0x6e369971, 0x5356b0c1, 0x70279f96, 0x4d47b626, 0x0ae7ccf6,
+		0x3787e546, 0x85a73956, 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457,
+		0x7d37fde7, 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7,
+		0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4, 0xe547aed4,
+		0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5, 0x1dd76a65, 0x5a7710b5,
+		0x67173905, 0xd537e515, 0xe857cca5, 0xaff7b675, 0x92979fc5, 0xe915e8db,
+		0xd475c16b, 0x93d5bbbb, 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b,
+		0x5b3534cb, 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da,
+		0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9, 0xf3352c39,
+		0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9, 0x3bd5a349, 0xb9853498,
+		0x84e51d28, 0xc34567f8, 0xfe254e48, 0x4c059258, 0x7165bbe8, 0x36c5c138,
+		0x0ba5e888, 0x28d4c7df, 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f,
+		0xe03448af, 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e,
+		0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e, 0x4834505d,
+		0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d, 0x80d4df2d, 0xc774a5fd,
+		0xfa148c4d, 0x78441b9c, 0x4524322c, 0x028448fc, 0x3fe4614c, 0x8dc4bd5c,
+		0xb0a494ec, 0xf704ee3c, 0xca64c78c},
+
+	{0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216, 0x50cd91b3, 0xd659e31d,
+		0x1d0530b8, 0xec53826d, 0x270f51c8, 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b,
+		0xbc9e13de, 0x3a0a6170, 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390,
+		0x85427035, 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6,
+		0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145, 0x39dc63eb,
+		0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d, 0x81387798, 0x9c3d4720,
+		0x57619485, 0xd1f5e62b, 0x1aa9358e, 0xebff875b, 0x20a354fe, 0xa6372650,
+		0x6d6bf5f5, 0x706ec54d, 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad,
+		0xcf26d408, 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0,
+		0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e, 0x73b8c7d6,
+		0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c, 0xc404d9c9, 0x4290ab67,
+		0x89cc78c2, 0x94c9487a, 0x5f959bdf, 0xd901e971, 0x125d3ad4, 0xe30b8801,
+		0x28575ba4, 0xaec3290a, 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c,
+		0xfe0eb8b9, 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1,
+		0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f, 0xad152b91,
+		0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987, 0xfdd8ba22, 0x08f40f5a,
+		0xc3a8dcff, 0x453cae51, 0x8e607df4, 0x93654d4c, 0x58399ee9, 0xdeadec47,
+		0x15f13fe2, 0xe4a78d37, 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21,
+		0xb46a1c84, 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca,
+		0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79, 0xe7718fac,
+		0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba, 0xb7bc1e1f, 0x31286cb1,
+		0xfa74bf14, 0x1eb014d8, 0xd5ecc77d, 0x5378b5d3, 0x98246676, 0x852156ce,
+		0x4e7d856b, 0xc8e9f7c5, 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be,
+		0x7477e41b, 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643,
+		0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0, 0xcb3ff55e,
+		0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525, 0x77a1e680, 0x6aa4d638,
+		0xa1f8059d, 0x276c7733, 0xec30a496, 0x191c11ee, 0xd240c24b, 0x54d4b0e5,
+		0x9f886340, 0x828d53f8, 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383,
+		0x3e134026, 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e,
+		0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db, 0x815b5163,
+		0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118, 0x3dc542bd, 0xbb513013,
+		0x700de3b6, 0x6d08d30e, 0xa65400ab, 0x20c07205, 0xeb9ca1a0, 0x11e81eb4,
+		0xdab4cd11, 0x5c20bfbf, 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9,
+		0x0ced2e0c, 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf,
+		0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a, 0x5ff6bd24,
+		0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32, 0x0f3b2c97, 0xfe6d9e42,
+		0x35314de7, 0xb3a53f49, 0x78f9ecec, 0x65fcdc54, 0xaea00ff1, 0x28347d5f,
+		0xe368aefa, 0x16441b82, 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994,
+		0x46898a31, 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4,
+		0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957, 0x15921919,
+		0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f, 0x455f88aa, 0xc3cbfa04,
+		0x089729a1, 0xf9c19b74, 0x329d48d1, 0xb4093a7f, 0x7f55e9da, 0x6250d962,
+		0xa90c0ac7, 0x2f987869, 0xe4c4abcc},
+
+	{0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413, 0x52382fa7, 0x63d0353a,
+		0xc5a73e8e, 0x33ef4e67, 0x959845d3, 0xa4705f4e, 0x020754fa, 0xc7a06a74,
+		0x61d761c0, 0x503f7b5d, 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7,
+		0x56368653, 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9,
+		0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e, 0x37e1e793,
+		0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5, 0xfe552301, 0x3bf21d8f,
+		0x9d85163b, 0xac6d0ca6, 0x0a1a0712, 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2,
+		0xcdba6d66, 0x081d53e8, 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552,
+		0x0e14aee6, 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068,
+		0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8, 0x6fc3cf26,
+		0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579, 0xe27c7ecd, 0xd3946450,
+		0x75e36fe4, 0xb044516a, 0x16335ade, 0x27db4043, 0x81ac4bf7, 0x77e43b1e,
+		0xd19330aa, 0xe07b2a37, 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24,
+		0xb2430590, 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4,
+		0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64, 0x87a5b6f9,
+		0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea, 0xd59d995e, 0x8bb64ce5,
+		0x2dc14751, 0x1c295dcc, 0xba5e5678, 0x7ff968f6, 0xd98e6342, 0xe86679df,
+		0x4e11726b, 0xb8590282, 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691,
+		0xea612d25, 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102,
+		0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5, 0xdf879e4c,
+		0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f, 0x8dbfb1eb, 0xbc57ab76,
+		0x1a20a0c2, 0x8816eaf2, 0x2e61e146, 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1,
+		0xda2ec555, 0xebc6dfc8, 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc,
+		0x8a11be08, 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c,
+		0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b, 0x8c184306,
+		0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972, 0xedcf22c6, 0x28681c48,
+		0x8e1f17fc, 0xbff70d61, 0x198006d5, 0x47abd36e, 0xe1dcd8da, 0xd034c247,
+		0x7643c9f3, 0xb3e4f77d, 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09,
+		0xd23396bd, 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833,
+		0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d, 0xd43a6bb3,
+		0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7, 0xb5ed0a73, 0x840510ee,
+		0x22721b5a, 0xe7d525d4, 0x41a22e60, 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b,
+		0x6a6a943f, 0x5b828ea2, 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1,
+		0x09baa105, 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff,
+		0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1, 0x3c5c126c,
+		0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f, 0x6e643dcb, 0x982c4d22,
+		0x3e5b4696, 0x0fb35c0b, 0xa9c457bf, 0x6c636931, 0xca146285, 0xfbfc7818,
+		0x5d8b73ac, 0x03a0a617, 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204,
+		0x519889b0, 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959,
+		0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe, 0x647e3ad9,
+		0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca, 0x3646157e, 0x07ae0fe3,
+		0xa1d90457, 0x579174be, 0xf1e67f0a, 0xc00e6597, 0x66796e23, 0xa3de50ad,
+		0x05a95b19, 0x34414184, 0x92364a30},
+
+	{0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa, 0x48e00e64, 0xc66f0987,
+		0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b, 0x91c01cc8, 0x5d6a1c56, 0x57af154f,
+		0x9b0515d1, 0x158a1232, 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656,
+		0xf23436c8, 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e,
+		0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa, 0x69312319,
+		0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b, 0x77f965b5, 0x7d3c6cac,
+		0xb1966c32, 0x3f196bd1, 0xf3b36b4f, 0x2a9379e3, 0xe639797d, 0x68b67e9e,
+		0xa41c7e00, 0xaed97719, 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d,
+		0x496753e3, 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa,
+		0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b, 0xd2624632,
+		0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed, 0xe537c273, 0x6bb8c590,
+		0xa712c50e, 0xadd7cc17, 0x617dcc89, 0xeff2cb6a, 0x2358cbf4, 0xfa78d958,
+		0x36d2d9c6, 0xb85dde25, 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df,
+		0xf0bdd041, 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c,
+		0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed, 0xc4e6ef0e,
+		0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4, 0x8c06e16a, 0xd0eba0bb,
+		0x1c41a025, 0x92cea7c6, 0x5e64a758, 0x54a1ae41, 0x980baedf, 0x1684a93c,
+		0xda2ea9a2, 0x030ebb0e, 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4,
+		0x4beeb56a, 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed,
+		0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889, 0x7fb58a25,
+		0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df, 0x37558441, 0xb9da83a2,
+		0x7570833c, 0x533b85da, 0x9f918544, 0x111e82a7, 0xddb48239, 0xd7718b20,
+		0x1bdb8bbe, 0x95548c5d, 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912,
+		0x0e51998c, 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1,
+		0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95, 0xe9efbd76,
+		0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839, 0x72eaa8a7, 0x782fa1be,
+		0xb485a120, 0x3a0aa6c3, 0xf6a0a65d, 0xaa4de78c, 0x66e7e712, 0xe868e0f1,
+		0x24c2e06f, 0x2e07e976, 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39,
+		0xb502fca7, 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be,
+		0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144, 0x52bcd85d,
+		0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12, 0xc9b9cd8c, 0x4736ca6f,
+		0x8b9ccaf1, 0x8159c3e8, 0x4df3c376, 0xc37cc495, 0x0fd6c40b, 0x7aa64737,
+		0xb60c47a9, 0x3883404a, 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0,
+		0x70634e2e, 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278,
+		0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682, 0x44387161,
+		0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b, 0x0cd87f05, 0xd5f86da9,
+		0x19526d37, 0x97dd6ad4, 0x5b776a4a, 0x51b26353, 0x9d1863cd, 0x1397642e,
+		0xdf3d64b0, 0x83d02561, 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b,
+		0xcb302b05, 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9,
+		0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd, 0xff6b144a,
+		0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0, 0xb78b1a2e, 0x39041dcd,
+		0xf5ae1d53, 0x2c8e0fff, 0xe0240f61, 0x6eab0882, 0xa201081c, 0xa8c40105,
+		0x646e019b, 0xeae10678, 0x264b06e6}}
+
+type dm_build_1097 interface {
+	dm_build_1098()
+	dm_build_1099() error
+	dm_build_1100()
+	dm_build_1101(imsg dm_build_1097) error
+	dm_build_1102() error
+	dm_build_1103() (interface{}, error)
+	dm_build_1104()
+	dm_build_1105(imsg dm_build_1097) (interface{}, error)
+	dm_build_1106()
+	dm_build_1107() error
+	dm_build_1108() byte
+	dm_build_1109(buffer *Dm_build_361, startOff int32, endOff int32) uint32
+	dm_build_1110() int32
+	dm_build_1111(length int32)
+	dm_build_1112() int16
+}
+
+type dm_build_1113 struct {
+	dm_build_1114 *dm_build_697
+
+	dm_build_1115 int16
+
+	dm_build_1116 int32
+
+	dm_build_1117 *DmStatement
+}
+
+func (dm_build_1119 *dm_build_1113) dm_build_1118(dm_build_1120 *dm_build_697, dm_build_1121 int16) *dm_build_1113 {
+	dm_build_1119.dm_build_1114 = dm_build_1120
+	dm_build_1119.dm_build_1115 = dm_build_1121
+	return dm_build_1119
+}
+
+func (dm_build_1123 *dm_build_1113) dm_build_1122(dm_build_1124 *dm_build_697, dm_build_1125 int16, dm_build_1126 *DmStatement) *dm_build_1113 {
+	dm_build_1123.dm_build_1118(dm_build_1124, dm_build_1125).dm_build_1117 = dm_build_1126
+	return dm_build_1123
+}
+
+func dm_build_1127(dm_build_1128 *dm_build_697, dm_build_1129 int16) *dm_build_1113 {
+	return new(dm_build_1113).dm_build_1118(dm_build_1128, dm_build_1129)
+}
+
+func dm_build_1130(dm_build_1131 *dm_build_697, dm_build_1132 int16, dm_build_1133 *DmStatement) *dm_build_1113 {
+	return new(dm_build_1113).dm_build_1122(dm_build_1131, dm_build_1132, dm_build_1133)
+}
+
+func (dm_build_1135 *dm_build_1113) dm_build_1098() {
+	dm_build_1135.dm_build_1114.dm_build_700.Dm_build_375(0)
+	dm_build_1135.dm_build_1114.dm_build_700.Dm_build_386(Dm_build_1005, true, true)
+}
+
+func (dm_build_1137 *dm_build_1113) dm_build_1099() error {
+	return nil
+}
+
+func (dm_build_1139 *dm_build_1113) dm_build_1100() {
+	if dm_build_1139.dm_build_1117 == nil {
+		dm_build_1139.dm_build_1114.dm_build_700.Dm_build_556(Dm_build_1007, 0)
+	} else {
+		dm_build_1139.dm_build_1114.dm_build_700.Dm_build_556(Dm_build_1007, dm_build_1139.dm_build_1117.id)
+	}
+
+	dm_build_1139.dm_build_1114.dm_build_700.Dm_build_552(Dm_build_1008, dm_build_1139.dm_build_1115)
+	dm_build_1139.dm_build_1114.dm_build_700.Dm_build_556(Dm_build_1009, int32(dm_build_1139.dm_build_1114.dm_build_700.Dm_build_373()-Dm_build_1005))
+}
+
+func (dm_build_1141 *dm_build_1113) dm_build_1102() error {
+	dm_build_1141.dm_build_1114.dm_build_700.Dm_build_378(0)
+	dm_build_1141.dm_build_1114.dm_build_700.Dm_build_386(Dm_build_1005, false, true)
+	return dm_build_1141.dm_build_1146()
+}
+
+func (dm_build_1143 *dm_build_1113) dm_build_1103() (interface{}, error) {
+	return nil, nil
+}
+
+func (dm_build_1145 *dm_build_1113) dm_build_1104() {
+}
+
+func (dm_build_1147 *dm_build_1113) dm_build_1146() error {
+	dm_build_1147.dm_build_1116 = dm_build_1147.dm_build_1114.dm_build_700.Dm_build_634(Dm_build_1010)
+	if dm_build_1147.dm_build_1116 < 0 && dm_build_1147.dm_build_1116 != EC_RN_EXCEED_ROWSET_SIZE.ErrCode {
+		return (&DmError{dm_build_1147.dm_build_1116, dm_build_1147.dm_build_1148(), nil, ""}).throw()
+	} else if dm_build_1147.dm_build_1116 > 0 {
+
+	} else if dm_build_1147.dm_build_1115 == Dm_build_1004 || dm_build_1147.dm_build_1115 == Dm_build_978 {
+		dm_build_1147.dm_build_1148()
+	}
+
+	return nil
+}
+
+func (dm_build_1149 *dm_build_1113) dm_build_1148() string {
+
+	dm_build_1150 := dm_build_1149.dm_build_1114.dm_build_701.getServerEncoding()
+
+	if dm_build_1150 != "" && dm_build_1150 == ENCODING_EUCKR && Locale != LANGUAGE_EN {
+		dm_build_1150 = ENCODING_GB18030
+	}
+
+	dm_build_1149.dm_build_1114.dm_build_700.Dm_build_386(int(dm_build_1149.dm_build_1114.dm_build_700.Dm_build_490()), false, true)
+
+	dm_build_1149.dm_build_1114.dm_build_700.Dm_build_386(int(dm_build_1149.dm_build_1114.dm_build_700.Dm_build_490()), false, true)
+
+	dm_build_1149.dm_build_1114.dm_build_700.Dm_build_386(int(dm_build_1149.dm_build_1114.dm_build_700.Dm_build_490()), false, true)
+
+	return dm_build_1149.dm_build_1114.dm_build_700.Dm_build_532(dm_build_1150, dm_build_1149.dm_build_1114.dm_build_701)
+}
+
+func (dm_build_1152 *dm_build_1113) dm_build_1101(dm_build_1153 dm_build_1097) (dm_build_1154 error) {
+	dm_build_1153.dm_build_1098()
+	if dm_build_1154 = dm_build_1153.dm_build_1099(); dm_build_1154 != nil {
+		return dm_build_1154
+	}
+	dm_build_1153.dm_build_1100()
+	return nil
+}
+
+func (dm_build_1156 *dm_build_1113) dm_build_1105(dm_build_1157 dm_build_1097) (dm_build_1158 interface{}, dm_build_1159 error) {
+	dm_build_1159 = dm_build_1157.dm_build_1102()
+	if dm_build_1159 != nil {
+		return nil, dm_build_1159
+	}
+	dm_build_1158, dm_build_1159 = dm_build_1157.dm_build_1103()
+	if dm_build_1159 != nil {
+		return nil, dm_build_1159
+	}
+	dm_build_1157.dm_build_1104()
+	return dm_build_1158, nil
+}
+
+func (dm_build_1161 *dm_build_1113) dm_build_1106() {
+	if dm_build_1161.dm_build_1114.dm_build_706 {
+
+		var orgLen = dm_build_1161.dm_build_1110()
+
+		dm_build_1161.dm_build_1111(orgLen + Dm_build_1095)
+		var crc = dm_build_1161.dm_build_1109(dm_build_1161.dm_build_1114.dm_build_700, 0, Dm_build_1005+orgLen)
+		dm_build_1161.dm_build_1114.dm_build_700.Dm_build_428(crc)
+	} else {
+		dm_build_1161.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1013, dm_build_1161.dm_build_1108())
+	}
+}
+
+func (dm_build_1163 *dm_build_1113) dm_build_1107() error {
+	if dm_build_1163.dm_build_1114.dm_build_706 {
+
+		var bodyLen = dm_build_1163.dm_build_1110() - Dm_build_1095
+		var msgLen = Dm_build_1005 + bodyLen
+		var recv = dm_build_1163.dm_build_1114.dm_build_700.Dm_build_652(int(msgLen))
+		var calc = dm_build_1163.dm_build_1109(dm_build_1163.dm_build_1114.dm_build_700, 0, msgLen)
+		if recv != calc {
+			return ECGO_MSG_CHECK_ERROR.throw()
+		}
+
+		dm_build_1163.dm_build_1111(bodyLen)
+		dm_build_1163.dm_build_1114.dm_build_700.Dm_build_375(int(msgLen))
+		return nil
+	} else {
+		var recv = dm_build_1163.dm_build_1114.dm_build_700.Dm_build_628(Dm_build_1013)
+		var calc = dm_build_1163.dm_build_1108()
+		if recv != calc {
+			return ECGO_MSG_CHECK_ERROR.throw()
+		}
+		return nil
+	}
+}
+
+func (dm_build_1165 *dm_build_1113) dm_build_1108() byte {
+	dm_build_1166 := dm_build_1165.dm_build_1114.dm_build_700.Dm_build_628(0)
+
+	for i := 1; i < Dm_build_1013; i++ {
+		dm_build_1166 ^= dm_build_1165.dm_build_1114.dm_build_700.Dm_build_628(i)
+	}
+
+	return dm_build_1166
+}
+
+func (dm_build_1168 *dm_build_1113) dm_build_1109(dm_build_1169 *Dm_build_361, dm_build_1170 int32, dm_build_1171 int32) uint32 {
+
+	var dm_build_1172 uint32 = 0xFFFFFFFF
+	var dm_build_1173 = dm_build_1170
+	var dm_build_1174 = dm_build_1171 - dm_build_1170
+	var dm_build_1175, dm_build_1176 uint32
+
+	for dm_build_1174 >= 8 {
+		dm_build_1175 = dm_build_1169.Dm_build_652(int(dm_build_1173)) ^ dm_build_1172
+		dm_build_1173 += ULINT_SIZE
+
+		dm_build_1176 = dm_build_1169.Dm_build_652(int(dm_build_1173))
+		dm_build_1173 += ULINT_SIZE
+
+		dm_build_1172 = Dm_build_1096[7][dm_build_1175&0xFF] ^ Dm_build_1096[6][(dm_build_1175>>8)&0xFF] ^
+			Dm_build_1096[5][(dm_build_1175>>16)&0xFF] ^ Dm_build_1096[4][(dm_build_1175>>24)&0xFF] ^
+			Dm_build_1096[3][dm_build_1176&0xFF] ^ Dm_build_1096[2][(dm_build_1176>>8)&0xFF] ^
+			Dm_build_1096[1][(dm_build_1176>>16)&0xFF] ^ Dm_build_1096[0][(dm_build_1176>>24)&0xFF]
+		dm_build_1174 -= 8
+	}
+
+	for dm_build_1174 > 0 {
+		dm_build_1172 = ((dm_build_1172 >> 8) & 0x00FFFFFF) ^ Dm_build_1096[0][(dm_build_1172&0xFF)^uint32(dm_build_1169.Dm_build_646(int(dm_build_1173)))]
+		dm_build_1173++
+		dm_build_1174--
+	}
+	return ^dm_build_1172
+}
+
+func (dm_build_1178 *dm_build_1113) dm_build_1110() int32 {
+	return dm_build_1178.dm_build_1114.dm_build_700.Dm_build_634(Dm_build_1009)
+}
+
+func (dm_build_1180 *dm_build_1113) dm_build_1111(dm_build_1181 int32) {
+	dm_build_1180.dm_build_1114.dm_build_700.Dm_build_556(Dm_build_1009, dm_build_1181)
+}
+
+func (dm_build_1183 *dm_build_1113) dm_build_1112() int16 {
+	return dm_build_1183.dm_build_1115
+}
+
+type dm_build_1184 struct {
+	dm_build_1113
+}
+
+func dm_build_1185(dm_build_1186 *dm_build_697) *dm_build_1184 {
+	dm_build_1187 := new(dm_build_1184)
+	dm_build_1187.dm_build_1118(dm_build_1186, Dm_build_985)
+	return dm_build_1187
+}
+
+type dm_build_1188 struct {
+	dm_build_1113
+	dm_build_1189 string
+}
+
+func dm_build_1190(dm_build_1191 *dm_build_697, dm_build_1192 *DmStatement, dm_build_1193 string) *dm_build_1188 {
+	dm_build_1194 := new(dm_build_1188)
+	dm_build_1194.dm_build_1122(dm_build_1191, Dm_build_993, dm_build_1192)
+	dm_build_1194.dm_build_1189 = dm_build_1193
+	dm_build_1194.dm_build_1117.cursorName = dm_build_1193
+	return dm_build_1194
+}
+
+func (dm_build_1196 *dm_build_1188) dm_build_1099() error {
+	dm_build_1196.dm_build_1114.dm_build_700.Dm_build_478(dm_build_1196.dm_build_1189, dm_build_1196.dm_build_1114.dm_build_701.getServerEncoding(), dm_build_1196.dm_build_1114.dm_build_701)
+	dm_build_1196.dm_build_1114.dm_build_700.Dm_build_416(1)
+	return nil
+}
+
+const Dm_build_1197 = 62
+
+type Dm_build_1198 struct {
+	dm_build_1221
+	dm_build_1199 []OptParameter
+}
+
+func dm_build_1200(dm_build_1201 *dm_build_697, dm_build_1202 *DmStatement, dm_build_1203 []OptParameter) *Dm_build_1198 {
+	dm_build_1204 := new(Dm_build_1198)
+	dm_build_1204.dm_build_1122(dm_build_1201, Dm_build_1003, dm_build_1202)
+	dm_build_1204.dm_build_1199 = dm_build_1203
+	return dm_build_1204
+}
+
+func (dm_build_1206 *Dm_build_1198) dm_build_1099() error {
+	dm_build_1207 := len(dm_build_1206.dm_build_1199)
+
+	if err := dm_build_1206.dm_build_1237(int32(dm_build_1207), 1); err != nil {
+		return err
+	}
+	dm_build_1206.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1197, 0)
+
+	if dm_build_1206.dm_build_1114.dm_build_701.MsgVersion >= Dm_build_970 {
+		dm_build_1206.dm_build_1252()
+		dm_build_1206.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1219, byte(dm_build_1206.dm_build_1224))
+	}
+
+	dm_build_1206.dm_build_1114.dm_build_700.Dm_build_478(dm_build_1206.dm_build_1117.nativeSql, dm_build_1206.dm_build_1117.dmConn.getServerEncoding(), dm_build_1206.dm_build_1117.dmConn)
+
+	for _, param := range dm_build_1206.dm_build_1199 {
+		dm_build_1206.dm_build_1114.dm_build_700.Dm_build_404(param.ioType)
+		dm_build_1206.dm_build_1114.dm_build_700.Dm_build_416(int32(param.tp))
+		dm_build_1206.dm_build_1114.dm_build_700.Dm_build_416(int32(param.prec))
+		dm_build_1206.dm_build_1114.dm_build_700.Dm_build_416(int32(param.scale))
+	}
+
+	for _, param := range dm_build_1206.dm_build_1199 {
+		if param.bytes == nil {
+			dm_build_1206.dm_build_1114.dm_build_700.Dm_build_424(uint16(Dm_build_1022))
+		} else {
+			var dataBytes = param.bytes[:len(param.bytes)]
+			if len(dataBytes) > int(Dm_build_1019) {
+				if dm_build_1206.dm_build_1114.dm_build_701.MsgVersion >= Dm_build_973 && len(dataBytes) < 0xffffffff &&
+					isComplexType(param.tp, param.scale) {
+					dm_build_1206.dm_build_1114.dm_build_700.Dm_build_424(uint16(Dm_build_1023))
+					dm_build_1206.dm_build_1114.dm_build_700.Dm_build_448(dataBytes)
+					continue
+				}
+				return ECGO_DATA_TOO_LONG.throw()
+			}
+			dm_build_1206.dm_build_1114.dm_build_700.Dm_build_454(dataBytes)
+		}
+	}
+	return nil
+}
+
+func (dm_build_1209 *Dm_build_1198) dm_build_1103() (interface{}, error) {
+	return dm_build_1209.dm_build_1221.dm_build_1103()
+}
+
+const (
+	Dm_build_1210 int = 0x01
+
+	Dm_build_1211 int = 0x02
+
+	Dm_build_1212 int = 0x04
+
+	Dm_build_1213 int = 0x08
+
+	Dm_build_1214 int = 0x0100
+
+	Dm_build_1215 int32 = 0x00
+
+	Dm_build_1216 int32 = 0x01
+
+	Dm_build_1217 int32 = 0x02
+
+	Dm_build_1218 int32 = 0x03
+
+	Dm_build_1219 = 48
+
+	Dm_build_1220 = 59
+)
+
+type dm_build_1221 struct {
+	dm_build_1113
+	dm_build_1222 [][]interface{}
+	dm_build_1223 []parameter
+
+	dm_build_1224 int32
+	dm_build_1225 int32
+	dm_build_1226 int32
+}
+
+func dm_build_1227(dm_build_1228 *dm_build_697, dm_build_1229 int16, dm_build_1230 *DmStatement) *dm_build_1221 {
+	dm_build_1231 := new(dm_build_1221)
+	dm_build_1231.dm_build_1122(dm_build_1228, dm_build_1229, dm_build_1230)
+
+	return dm_build_1231
+}
+
+func dm_build_1232(dm_build_1233 *dm_build_697, dm_build_1234 *DmStatement, dm_build_1235 [][]interface{}) *dm_build_1221 {
+	dm_build_1236 := new(dm_build_1221)
+
+	if dm_build_1233.dm_build_701.Execute2 {
+		dm_build_1236.dm_build_1122(dm_build_1233, Dm_build_987, dm_build_1234)
+	} else {
+		dm_build_1236.dm_build_1122(dm_build_1233, Dm_build_983, dm_build_1234)
+	}
+
+	dm_build_1236.dm_build_1223 = dm_build_1234.bindParams
+	dm_build_1236.dm_build_1222 = dm_build_1235
+
+	return dm_build_1236
+}
+
+func (dm_build_1238 *dm_build_1221) dm_build_1237(dm_build_1239 int32, dm_build_1240 int64) error {
+
+	dm_build_1241 := Dm_build_1006
+
+	if dm_build_1238.dm_build_1114.dm_build_701.autoCommit {
+		dm_build_1241 += dm_build_1238.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1241, 1)
+	} else {
+		dm_build_1241 += dm_build_1238.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1241, 0)
+	}
+
+	if dm_build_1239 > PARAM_COUNT_LIMIT {
+		return ECGO_PARAM_COUNT_LIMIT.throw()
+	}
+	dm_build_1241 += dm_build_1238.dm_build_1114.dm_build_700.Dm_build_576(dm_build_1241, uint16(dm_build_1239))
+
+	dm_build_1241 += dm_build_1238.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1241, 1)
+
+	dm_build_1241 += dm_build_1238.dm_build_1114.dm_build_700.Dm_build_560(dm_build_1241, dm_build_1240)
+
+	dm_build_1241 += dm_build_1238.dm_build_1114.dm_build_700.Dm_build_560(dm_build_1241, dm_build_1238.dm_build_1117.cursorUpdateRow)
+
+	if dm_build_1238.dm_build_1117.maxRows <= 0 || dm_build_1238.dm_build_1117.dmConn.dmConnector.enRsCache {
+		dm_build_1241 += dm_build_1238.dm_build_1114.dm_build_700.Dm_build_560(dm_build_1241, INT64_MAX)
+	} else {
+		dm_build_1241 += dm_build_1238.dm_build_1114.dm_build_700.Dm_build_560(dm_build_1241, dm_build_1238.dm_build_1117.maxRows)
+	}
+
+	dm_build_1241 += dm_build_1238.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1241, 1)
+
+	if dm_build_1238.dm_build_1114.dm_build_701.dmConnector.continueBatchOnError {
+		dm_build_1241 += dm_build_1238.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1241, 1)
+	} else {
+		dm_build_1241 += dm_build_1238.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1241, 0)
+	}
+
+	dm_build_1241 += dm_build_1238.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1241, 0)
+
+	dm_build_1241 += dm_build_1238.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1241, 0)
+
+	if dm_build_1238.dm_build_1117.queryTimeout == 0 {
+		dm_build_1241 += dm_build_1238.dm_build_1114.dm_build_700.Dm_build_556(dm_build_1241, -1)
+	} else {
+		dm_build_1241 += dm_build_1238.dm_build_1114.dm_build_700.Dm_build_556(dm_build_1241, dm_build_1238.dm_build_1117.queryTimeout)
+	}
+
+	dm_build_1241 += dm_build_1238.dm_build_1114.dm_build_700.Dm_build_556(dm_build_1241, dm_build_1238.dm_build_1114.dm_build_701.dmConnector.batchAllowMaxErrors)
+
+	if dm_build_1238.dm_build_1117.innerExec {
+		dm_build_1241 += dm_build_1238.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1241, 1)
+	} else {
+		dm_build_1241 += dm_build_1238.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1241, 0)
+	}
+	return nil
+}
+
+func (dm_build_1243 *dm_build_1221) dm_build_1099() error {
+	var dm_build_1244 int32
+	var dm_build_1245 int64
+
+	if dm_build_1243.dm_build_1223 != nil {
+		dm_build_1244 = int32(len(dm_build_1243.dm_build_1223))
+	} else {
+		dm_build_1244 = 0
+	}
+
+	if dm_build_1243.dm_build_1222 != nil {
+		dm_build_1245 = int64(len(dm_build_1243.dm_build_1222))
+	} else {
+		dm_build_1245 = 0
+	}
+
+	if err := dm_build_1243.dm_build_1237(dm_build_1244, dm_build_1245); err != nil {
+		return err
+	}
+
+	if dm_build_1243.dm_build_1114.dm_build_701.MsgVersion >= Dm_build_970 {
+		dm_build_1243.dm_build_1252()
+		dm_build_1243.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1219, byte(dm_build_1243.dm_build_1224))
+	}
+
+	if dm_build_1244 > 0 {
+		err := dm_build_1243.dm_build_1246(dm_build_1243.dm_build_1223)
+		if err != nil {
+			return err
+		}
+		if dm_build_1243.dm_build_1222 != nil && len(dm_build_1243.dm_build_1222) > 0 {
+			for _, paramObject := range dm_build_1243.dm_build_1222 {
+				if err := dm_build_1243.dm_build_1249(paramObject); err != nil {
+					return err
+				}
+			}
+		}
+	}
+
+	return nil
+}
+
+func (dm_build_1247 *dm_build_1221) dm_build_1246(dm_build_1248 []parameter) error {
+	for _, param := range dm_build_1248 {
+		if param.mask == MASK_ORACLE_DATE {
+
+			param.scale = param.scale | ORACLE_DATE_SCALE_MASK
+		} else if param.mask == MASK_LOCAL_DATETIME {
+
+			param.scale = param.scale | LOCAL_DATETIME_SCALE_MASK
+		} else if param.mask == MASK_ORACLE_FLOAT {
+
+			param.prec = int32(math.Round(float64(param.prec) * 3.32193))
+			param.scale = ORACLE_FLOAT_SCALE_MASK
+		}
+
+		if param.colType == CURSOR && param.ioType == IO_TYPE_OUT {
+			dm_build_1247.dm_build_1114.dm_build_700.Dm_build_408(IO_TYPE_INOUT)
+		} else {
+			dm_build_1247.dm_build_1114.dm_build_700.Dm_build_408(param.ioType)
+		}
+
+		dm_build_1247.dm_build_1114.dm_build_700.Dm_build_416(param.colType)
+
+		lprec := param.prec
+		lscale := param.scale
+		typeDesc := param.typeDescriptor
+		switch param.colType {
+		case ARRAY, SARRAY:
+			tmp, err := getPackArraySize(typeDesc)
+			if err != nil {
+				return err
+			}
+			lprec = int32(tmp)
+		case PLTYPE_RECORD:
+			tmp, err := getPackRecordSize(typeDesc)
+			if err != nil {
+				return err
+			}
+			lprec = int32(tmp)
+		case CLASS:
+			tmp, err := getPackClassSize(typeDesc)
+			if err != nil {
+				return err
+			}
+			lprec = int32(tmp)
+		case BLOB:
+			if isComplexType(int(param.colType), int(param.scale)) {
+				lprec = int32(typeDesc.getObjId())
+				if lprec == 4 {
+					lprec = int32(typeDesc.getOuterId())
+				}
+			}
+		}
+
+		dm_build_1247.dm_build_1114.dm_build_700.Dm_build_416(lprec)
+
+		dm_build_1247.dm_build_1114.dm_build_700.Dm_build_416(lscale)
+
+		switch param.colType {
+		case ARRAY, SARRAY:
+			err := packArray(typeDesc, dm_build_1247.dm_build_1114.dm_build_700)
+			if err != nil {
+				return err
+			}
+
+		case PLTYPE_RECORD:
+			err := packRecord(typeDesc, dm_build_1247.dm_build_1114.dm_build_700)
+			if err != nil {
+				return err
+			}
+
+		case CLASS:
+			err := packClass(typeDesc, dm_build_1247.dm_build_1114.dm_build_700)
+			if err != nil {
+				return err
+			}
+
+		}
+	}
+
+	return nil
+}
+
+func (dm_build_1250 *dm_build_1221) dm_build_1249(dm_build_1251 []interface{}) error {
+	for i := 0; i < len(dm_build_1250.dm_build_1223); i++ {
+
+		if dm_build_1250.dm_build_1223[i].colType == CURSOR {
+			dm_build_1250.dm_build_1114.dm_build_700.Dm_build_412(ULINT_SIZE)
+			dm_build_1250.dm_build_1114.dm_build_700.Dm_build_416(dm_build_1250.dm_build_1223[i].cursorStmt.id)
+			continue
+		}
+
+		if dm_build_1250.dm_build_1223[i].ioType == IO_TYPE_OUT {
+			continue
+		}
+
+		if dm_build_1251[i] == nil {
+			dm_build_1250.dm_build_1114.dm_build_700.Dm_build_424(uint16(Dm_build_1022))
+		} else {
+			switch dm_build_1251[i].(type) {
+			case []byte:
+				if dataBytes, ok := dm_build_1251[i].([]byte); ok {
+					if len(dataBytes) > int(Dm_build_1019) {
+						if dm_build_1250.dm_build_1114.dm_build_701.MsgVersion >= Dm_build_973 && len(dataBytes) < 0xffffffff &&
+							isComplexType(int(dm_build_1250.dm_build_1223[i].colType), int(dm_build_1250.dm_build_1223[i].scale)) {
+							dm_build_1250.dm_build_1114.dm_build_700.Dm_build_424(uint16(Dm_build_1023))
+							dm_build_1250.dm_build_1114.dm_build_700.Dm_build_448(dataBytes)
+							continue
+						}
+						return ECGO_DATA_TOO_LONG.throw()
+					}
+					dm_build_1250.dm_build_1114.dm_build_700.Dm_build_454(dataBytes)
+				}
+			case int:
+				if dm_build_1251[i] == ParamDataEnum_Null {
+					dm_build_1250.dm_build_1114.dm_build_700.Dm_build_424(uint16(Dm_build_1022))
+				} else if dm_build_1251[i] == ParamDataEnum_OFF_ROW {
+					dm_build_1250.dm_build_1114.dm_build_700.Dm_build_412(0)
+				}
+			case lobCtl:
+				dm_build_1250.dm_build_1114.dm_build_700.Dm_build_424(uint16(Dm_build_1020))
+				dm_build_1250.dm_build_1114.dm_build_700.Dm_build_444(dm_build_1251[i].(lobCtl).value)
+			default:
+				return fmt.Errorf("Bind param data failed by invalid param data type: ")
+			}
+		}
+	}
+
+	return nil
+}
+
+func (dm_build_1253 *dm_build_1221) dm_build_1252() int32 {
+	dm_build_1253.dm_build_1224 = Dm_build_1216
+	dm_build_1253.dm_build_1225 = 1
+	return dm_build_1253.dm_build_1224
+}
+
+func (dm_build_1255 *dm_build_1221) dm_build_1103() (interface{}, error) {
+	dm_build_1256 := execRetInfo{}
+	dm_build_1257 := dm_build_1255.dm_build_1117.dmConn
+
+	dm_build_1258 := Dm_build_1006
+
+	dm_build_1256.retSqlType = dm_build_1255.dm_build_1114.dm_build_700.Dm_build_631(dm_build_1258)
+	dm_build_1258 += USINT_SIZE
+
+	dm_build_1259 := dm_build_1255.dm_build_1114.dm_build_700.Dm_build_631(dm_build_1258)
+	dm_build_1258 += USINT_SIZE
+
+	dm_build_1256.updateCount = dm_build_1255.dm_build_1114.dm_build_700.Dm_build_637(dm_build_1258)
+	dm_build_1258 += DDWORD_SIZE
+
+	dm_build_1260 := dm_build_1255.dm_build_1114.dm_build_700.Dm_build_649(dm_build_1258)
+	dm_build_1258 += USINT_SIZE
+
+	dm_build_1256.rsUpdatable = dm_build_1255.dm_build_1114.dm_build_700.Dm_build_628(dm_build_1258) != 0
+	dm_build_1258 += BYTE_SIZE
+
+	dm_build_1261 := dm_build_1255.dm_build_1114.dm_build_700.Dm_build_631(dm_build_1258)
+	dm_build_1258 += ULINT_SIZE
+
+	dm_build_1256.printLen = dm_build_1255.dm_build_1114.dm_build_700.Dm_build_634(dm_build_1258)
+	dm_build_1258 += ULINT_SIZE
+
+	var dm_build_1262 int16 = -1
+	if dm_build_1256.retSqlType == Dm_build_1072 || dm_build_1256.retSqlType == Dm_build_1073 {
+		dm_build_1256.rowid = 0
+
+		dm_build_1256.rsBdta = dm_build_1255.dm_build_1114.dm_build_700.Dm_build_628(dm_build_1258) == Dm_build_1085
+		dm_build_1258 += BYTE_SIZE
+
+		dm_build_1262 = dm_build_1255.dm_build_1114.dm_build_700.Dm_build_631(dm_build_1258)
+		dm_build_1258 += USINT_SIZE
+		dm_build_1258 += 5
+	} else {
+		dm_build_1256.rowid = dm_build_1255.dm_build_1114.dm_build_700.Dm_build_637(dm_build_1258)
+		dm_build_1258 += DDWORD_SIZE
+	}
+
+	dm_build_1256.execId = dm_build_1255.dm_build_1114.dm_build_700.Dm_build_634(dm_build_1258)
+	dm_build_1258 += ULINT_SIZE
+
+	dm_build_1256.rsCacheOffset = dm_build_1255.dm_build_1114.dm_build_700.Dm_build_634(dm_build_1258)
+	dm_build_1258 += ULINT_SIZE
+
+	dm_build_1263 := dm_build_1255.dm_build_1114.dm_build_700.Dm_build_628(dm_build_1258)
+	dm_build_1258 += BYTE_SIZE
+	dm_build_1264 := (dm_build_1263 & 0x01) == 0x01
+
+	dm_build_1257.TrxStatus = dm_build_1255.dm_build_1114.dm_build_700.Dm_build_634(dm_build_1258)
+	dm_build_1257.setTrxFinish(dm_build_1257.TrxStatus)
+	dm_build_1258 += ULINT_SIZE
+
+	if dm_build_1256.printLen > 0 {
+		bytes := dm_build_1255.dm_build_1114.dm_build_700.Dm_build_511(int(dm_build_1256.printLen))
+		dm_build_1256.printMsg = Dm_build_1.Dm_build_158(bytes, 0, len(bytes), dm_build_1257.getServerEncoding(), dm_build_1257)
+	}
+
+	if dm_build_1260 > 0 {
+		dm_build_1256.outParamDatas = dm_build_1255.dm_build_1265(int(dm_build_1260))
+	}
+
+	switch dm_build_1256.retSqlType {
+	case Dm_build_1074:
+		dm_build_1257.dmConnector.localTimezone = dm_build_1255.dm_build_1114.dm_build_700.Dm_build_487()
+	case Dm_build_1072:
+		dm_build_1256.hasResultSet = true
+		if dm_build_1259 > 0 {
+			dm_build_1255.dm_build_1117.columns = dm_build_1255.dm_build_1274(int(dm_build_1259), dm_build_1256.rsBdta)
+		}
+		dm_build_1255.dm_build_1284(&dm_build_1256, len(dm_build_1255.dm_build_1117.columns), int(dm_build_1261), int(dm_build_1262))
+	case Dm_build_1073:
+		if dm_build_1259 > 0 || dm_build_1261 > 0 {
+			dm_build_1256.hasResultSet = true
+		}
+		if dm_build_1259 > 0 {
+			dm_build_1255.dm_build_1117.columns = dm_build_1255.dm_build_1274(int(dm_build_1259), dm_build_1256.rsBdta)
+		}
+		dm_build_1255.dm_build_1284(&dm_build_1256, len(dm_build_1255.dm_build_1117.columns), int(dm_build_1261), int(dm_build_1262))
+	case Dm_build_1075:
+		dm_build_1257.IsoLevel = int32(dm_build_1255.dm_build_1114.dm_build_700.Dm_build_487())
+		dm_build_1257.ReadOnly = dm_build_1255.dm_build_1114.dm_build_700.Dm_build_484() == 1
+	case Dm_build_1068:
+		dm_build_1257.Schema = dm_build_1255.dm_build_1114.dm_build_700.Dm_build_532(dm_build_1257.getServerEncoding(), dm_build_1257)
+	case Dm_build_1065:
+		dm_build_1256.explain = dm_build_1255.dm_build_1114.dm_build_700.Dm_build_532(dm_build_1257.getServerEncoding(), dm_build_1257)
+
+	case Dm_build_1069, Dm_build_1071, Dm_build_1070:
+		if dm_build_1264 {
+
+			counts := dm_build_1255.dm_build_1114.dm_build_700.Dm_build_490()
+			rowCounts := make([]int64, counts)
+			for i := 0; i < int(counts); i++ {
+				rowCounts[i] = dm_build_1255.dm_build_1114.dm_build_700.Dm_build_493()
+			}
+			dm_build_1256.updateCounts = rowCounts
+		}
+
+		dm_build_1255.dm_build_1295(&dm_build_1256)
+
+		if dm_build_1255.dm_build_1116 == EC_BP_WITH_ERROR.ErrCode {
+			dm_build_1255.dm_build_1290(dm_build_1256.updateCounts)
+		}
+	case Dm_build_1078:
+		len := dm_build_1255.dm_build_1114.dm_build_700.Dm_build_502()
+		dm_build_1257.FormatDate = dm_build_1255.dm_build_1114.dm_build_700.Dm_build_527(int(len), dm_build_1257.getServerEncoding(), dm_build_1257)
+	case Dm_build_1080:
+
+		len := dm_build_1255.dm_build_1114.dm_build_700.Dm_build_502()
+		dm_build_1257.FormatTimestamp = dm_build_1255.dm_build_1114.dm_build_700.Dm_build_527(int(len), dm_build_1257.getServerEncoding(), dm_build_1257)
+	case Dm_build_1081:
+
+		len := dm_build_1255.dm_build_1114.dm_build_700.Dm_build_502()
+		dm_build_1257.FormatTimestampTZ = dm_build_1255.dm_build_1114.dm_build_700.Dm_build_527(int(len), dm_build_1257.getServerEncoding(), dm_build_1257)
+	case Dm_build_1079:
+		len := dm_build_1255.dm_build_1114.dm_build_700.Dm_build_502()
+		dm_build_1257.FormatTime = dm_build_1255.dm_build_1114.dm_build_700.Dm_build_527(int(len), dm_build_1257.getServerEncoding(), dm_build_1257)
+	case Dm_build_1082:
+		len := dm_build_1255.dm_build_1114.dm_build_700.Dm_build_502()
+		dm_build_1257.FormatTimeTZ = dm_build_1255.dm_build_1114.dm_build_700.Dm_build_527(int(len), dm_build_1257.getServerEncoding(), dm_build_1257)
+	case Dm_build_1083:
+		dm_build_1257.OracleDateLanguage = dm_build_1255.dm_build_1114.dm_build_700.Dm_build_502()
+	}
+
+	return &dm_build_1256, nil
+}
+
+func (dm_build_1266 *dm_build_1221) dm_build_1265(dm_build_1267 int) [][]byte {
+	dm_build_1268 := make([]int, dm_build_1267)
+
+	dm_build_1269 := 0
+	for i := 0; i < len(dm_build_1266.dm_build_1223); i++ {
+		if dm_build_1266.dm_build_1223[i].ioType == IO_TYPE_INOUT || dm_build_1266.dm_build_1223[i].ioType == IO_TYPE_OUT {
+			dm_build_1268[dm_build_1269] = i
+			dm_build_1269++
+		}
+	}
+
+	dm_build_1270 := make([][]byte, len(dm_build_1266.dm_build_1223))
+	var dm_build_1271 int32
+	var dm_build_1272 bool
+	var dm_build_1273 []byte = nil
+	for i := 0; i < dm_build_1267; i++ {
+		dm_build_1272 = false
+		dm_build_1271 = int32(dm_build_1266.dm_build_1114.dm_build_700.Dm_build_505())
+
+		if dm_build_1271 == int32(Dm_build_1022) {
+			dm_build_1271 = 0
+			dm_build_1272 = true
+		} else if dm_build_1271 == int32(Dm_build_1023) {
+			dm_build_1271 = dm_build_1266.dm_build_1114.dm_build_700.Dm_build_490()
+		}
+
+		if dm_build_1272 {
+			dm_build_1270[dm_build_1268[i]] = nil
+		} else {
+			dm_build_1273 = dm_build_1266.dm_build_1114.dm_build_700.Dm_build_511(int(dm_build_1271))
+			dm_build_1270[dm_build_1268[i]] = dm_build_1273
+		}
+	}
+
+	return dm_build_1270
+}
+
+func (dm_build_1275 *dm_build_1221) dm_build_1274(dm_build_1276 int, dm_build_1277 bool) []column {
+	dm_build_1278 := dm_build_1275.dm_build_1114.dm_build_701.getServerEncoding()
+	var dm_build_1279, dm_build_1280, dm_build_1281, dm_build_1282 int16
+	dm_build_1283 := make([]column, dm_build_1276)
+	for i := 0; i < dm_build_1276; i++ {
+		dm_build_1283[i].InitColumn()
+
+		dm_build_1283[i].colType = dm_build_1275.dm_build_1114.dm_build_700.Dm_build_490()
+
+		dm_build_1283[i].prec = dm_build_1275.dm_build_1114.dm_build_700.Dm_build_490()
+
+		dm_build_1283[i].scale = dm_build_1275.dm_build_1114.dm_build_700.Dm_build_490()
+
+		dm_build_1283[i].nullable = dm_build_1275.dm_build_1114.dm_build_700.Dm_build_490() != 0
+
+		itemFlag := dm_build_1275.dm_build_1114.dm_build_700.Dm_build_487()
+		dm_build_1283[i].lob = int(itemFlag)&Dm_build_1211 != 0
+		dm_build_1283[i].identity = int(itemFlag)&Dm_build_1210 != 0
+		dm_build_1283[i].readonly = int(itemFlag)&Dm_build_1212 != 0
+
+		dm_build_1275.dm_build_1114.dm_build_700.Dm_build_386(4, false, true)
+
+		dm_build_1275.dm_build_1114.dm_build_700.Dm_build_386(2, false, true)
+
+		dm_build_1279 = dm_build_1275.dm_build_1114.dm_build_700.Dm_build_487()
+
+		dm_build_1280 = dm_build_1275.dm_build_1114.dm_build_700.Dm_build_487()
+
+		dm_build_1281 = dm_build_1275.dm_build_1114.dm_build_700.Dm_build_487()
+
+		dm_build_1282 = dm_build_1275.dm_build_1114.dm_build_700.Dm_build_487()
+		dm_build_1283[i].name = dm_build_1275.dm_build_1114.dm_build_700.Dm_build_527(int(dm_build_1279), dm_build_1278, dm_build_1275.dm_build_1114.dm_build_701)
+		dm_build_1283[i].typeName = dm_build_1275.dm_build_1114.dm_build_700.Dm_build_527(int(dm_build_1280), dm_build_1278, dm_build_1275.dm_build_1114.dm_build_701)
+		dm_build_1283[i].tableName = dm_build_1275.dm_build_1114.dm_build_700.Dm_build_527(int(dm_build_1281), dm_build_1278, dm_build_1275.dm_build_1114.dm_build_701)
+		dm_build_1283[i].schemaName = dm_build_1275.dm_build_1114.dm_build_700.Dm_build_527(int(dm_build_1282), dm_build_1278, dm_build_1275.dm_build_1114.dm_build_701)
+
+		if dm_build_1275.dm_build_1117.readBaseColName {
+			dm_build_1283[i].baseName = dm_build_1275.dm_build_1114.dm_build_700.Dm_build_540(dm_build_1278, dm_build_1275.dm_build_1114.dm_build_701)
+		}
+
+		if dm_build_1283[i].lob {
+			dm_build_1283[i].lobTabId = dm_build_1275.dm_build_1114.dm_build_700.Dm_build_490()
+			dm_build_1283[i].lobColId = dm_build_1275.dm_build_1114.dm_build_700.Dm_build_487()
+		}
+
+		if dm_build_1283[i].colType == DATETIME || dm_build_1283[i].colType == DATETIME2 {
+			if (dm_build_1283[i].scale & LOCAL_DATETIME_SCALE_MASK) != 0 {
+
+				dm_build_1283[i].scale = dm_build_1283[i].scale & ^LOCAL_DATETIME_SCALE_MASK
+				dm_build_1283[i].mask = MASK_LOCAL_DATETIME
+			} else if (dm_build_1283[i].scale & ORACLE_DATE_SCALE_MASK) != 0 {
+
+				dm_build_1283[i].scale = dm_build_1283[i].scale & ^ORACLE_DATE_SCALE_MASK
+				dm_build_1283[i].mask = MASK_ORACLE_DATE
+			}
+		}
+
+		if dm_build_1283[i].colType == DECIMAL && dm_build_1283[i].scale == ORACLE_FLOAT_SCALE_MASK {
+			dm_build_1283[i].prec = int32(math.Round(float64(dm_build_1283[i].prec)*0.30103) + 1)
+			dm_build_1283[i].scale = -1
+			dm_build_1283[i].mask = MASK_ORACLE_FLOAT
+		}
+
+		if dm_build_1283[i].colType == VARCHAR && dm_build_1283[i].prec == BFILE_PREC && dm_build_1283[i].scale == BFILE_SCALE {
+			dm_build_1283[i].mask = MASK_BFILE
+		}
+	}
+
+	for i := 0; i < dm_build_1276; i++ {
+
+		if isComplexType(int(dm_build_1283[i].colType), int(dm_build_1283[i].scale)) {
+			strDesc := newTypeDescriptor(dm_build_1275.dm_build_1114.dm_build_701)
+			strDesc.unpack(dm_build_1275.dm_build_1114.dm_build_700)
+			dm_build_1283[i].typeDescriptor = strDesc
+		}
+	}
+
+	return dm_build_1283
+}
+
+func (dm_build_1285 *dm_build_1221) dm_build_1284(dm_build_1286 *execRetInfo, dm_build_1287 int, dm_build_1288 int, dm_build_1289 int) {
+	if dm_build_1288 > 0 {
+		startOffset := dm_build_1285.dm_build_1114.dm_build_700.Dm_build_381()
+		if dm_build_1286.rsBdta {
+			dm_build_1286.rsDatas = dm_build_1285.dm_build_1308(dm_build_1285.dm_build_1117.columns, dm_build_1289)
+		} else {
+			datas := make([][][]byte, dm_build_1288)
+
+			for i := 0; i < dm_build_1288; i++ {
+
+				datas[i] = make([][]byte, dm_build_1287+1)
+
+				dm_build_1285.dm_build_1114.dm_build_700.Dm_build_386(2, false, true)
+
+				datas[i][0] = dm_build_1285.dm_build_1114.dm_build_700.Dm_build_511(LINT64_SIZE)
+
+				dm_build_1285.dm_build_1114.dm_build_700.Dm_build_386(2*dm_build_1287, false, true)
+
+				for j := 1; j < dm_build_1287+1; j++ {
+
+					colLen := dm_build_1285.dm_build_1114.dm_build_700.Dm_build_505()
+					if colLen == Dm_build_1026 {
+						datas[i][j] = nil
+					} else if colLen != Dm_build_1027 {
+						datas[i][j] = dm_build_1285.dm_build_1114.dm_build_700.Dm_build_511(int(colLen))
+					} else {
+						datas[i][j] = dm_build_1285.dm_build_1114.dm_build_700.Dm_build_515()
+					}
+				}
+			}
+
+			dm_build_1286.rsDatas = datas
+		}
+		dm_build_1286.rsSizeof = dm_build_1285.dm_build_1114.dm_build_700.Dm_build_381() - startOffset
+	}
+
+	if dm_build_1286.rsCacheOffset > 0 {
+		tbCount := dm_build_1285.dm_build_1114.dm_build_700.Dm_build_487()
+
+		ids := make([]int32, tbCount)
+		tss := make([]int64, tbCount)
+
+		for i := 0; i < int(tbCount); i++ {
+			ids[i] = dm_build_1285.dm_build_1114.dm_build_700.Dm_build_490()
+			tss[i] = dm_build_1285.dm_build_1114.dm_build_700.Dm_build_493()
+		}
+
+		dm_build_1286.tbIds = ids[:]
+		dm_build_1286.tbTss = tss[:]
+	}
+}
+
+func (dm_build_1291 *dm_build_1221) dm_build_1290(dm_build_1292 []int64) error {
+
+	dm_build_1291.dm_build_1114.dm_build_700.Dm_build_386(4, false, true)
+
+	dm_build_1293 := dm_build_1291.dm_build_1114.dm_build_700.Dm_build_490()
+
+	dm_build_1294 := make([]string, 0, 8)
+	for i := 0; i < int(dm_build_1293); i++ {
+		irow := dm_build_1291.dm_build_1114.dm_build_700.Dm_build_490()
+
+		dm_build_1292[irow] = -3
+
+		code := dm_build_1291.dm_build_1114.dm_build_700.Dm_build_490()
+
+		errStr := dm_build_1291.dm_build_1114.dm_build_700.Dm_build_540(dm_build_1291.dm_build_1114.dm_build_701.getServerEncoding(), dm_build_1291.dm_build_1114.dm_build_701)
+
+		dm_build_1294 = append(dm_build_1294, "row["+strconv.Itoa(int(irow))+"]:"+strconv.Itoa(int(code))+", "+errStr)
+	}
+
+	if len(dm_build_1294) > 0 {
+		builder := &strings.Builder{}
+		for _, str := range dm_build_1294 {
+			builder.WriteString(util.LINE_SEPARATOR)
+			builder.WriteString(str)
+		}
+		EC_BP_WITH_ERROR.ErrText += builder.String()
+		return EC_BP_WITH_ERROR.throw()
+	}
+	return nil
+}
+
+func (dm_build_1296 *dm_build_1221) dm_build_1295(dm_build_1297 *execRetInfo) error {
+	dm_build_1298 := dm_build_1296.dm_build_1114.dm_build_700.Dm_build_628(Dm_build_1220)
+	dm_build_1299 := (dm_build_1298 & 0x02) == 0x02
+	if !dm_build_1299 {
+
+		if dm_build_1297.updateCount == 1 {
+
+			dm_build_1297.lastInsertId = dm_build_1297.rowid
+		}
+		return nil
+	}
+
+	if dm_build_1296.dm_build_1114.dm_build_701.MsgVersion < Dm_build_970 || dm_build_1296.dm_build_1224 == Dm_build_1216 {
+
+		rows := dm_build_1296.dm_build_1114.dm_build_700.Dm_build_490()
+		var lastInsertId int64
+		for i := 0; i < int(rows); i++ {
+			lastInsertId = dm_build_1296.dm_build_1114.dm_build_700.Dm_build_493()
+		}
+		dm_build_1297.lastInsertId = lastInsertId
+	} else {
+
+	}
+
+	return nil
+}
+
+const (
+	Dm_build_1300 = 0
+
+	Dm_build_1301 = Dm_build_1300 + ULINT_SIZE
+
+	Dm_build_1302 = Dm_build_1301 + USINT_SIZE
+
+	Dm_build_1303 = Dm_build_1302 + ULINT_SIZE
+
+	Dm_build_1304 = Dm_build_1303 + ULINT_SIZE
+
+	Dm_build_1305 = Dm_build_1304 + BYTE_SIZE
+
+	Dm_build_1306 = -2
+
+	Dm_build_1307 = -3
+)
+
+func (dm_build_1309 *dm_build_1221) dm_build_1308(dm_build_1310 []column, dm_build_1311 int) [][][]byte {
+
+	dm_build_1312 := dm_build_1309.dm_build_1114.dm_build_700.Dm_build_508()
+
+	dm_build_1313 := dm_build_1309.dm_build_1114.dm_build_700.Dm_build_505()
+
+	var dm_build_1314 bool
+
+	if dm_build_1311 >= 0 && int(dm_build_1313) == len(dm_build_1310)+1 {
+		dm_build_1314 = true
+	} else {
+		dm_build_1314 = false
+	}
+
+	dm_build_1309.dm_build_1114.dm_build_700.Dm_build_386(ULINT_SIZE, false, true)
+
+	dm_build_1309.dm_build_1114.dm_build_700.Dm_build_386(ULINT_SIZE, false, true)
+
+	dm_build_1309.dm_build_1114.dm_build_700.Dm_build_386(BYTE_SIZE, false, true)
+
+	dm_build_1315 := make([]uint16, dm_build_1313)
+	for icol := 0; icol < int(dm_build_1313); icol++ {
+		dm_build_1315[icol] = dm_build_1309.dm_build_1114.dm_build_700.Dm_build_505()
+	}
+
+	dm_build_1316 := make([]uint32, dm_build_1313)
+	dm_build_1317 := make([][][]byte, dm_build_1312)
+
+	for i := uint32(0); i < dm_build_1312; i++ {
+		dm_build_1317[i] = make([][]byte, len(dm_build_1310)+1)
+	}
+
+	for icol := 0; icol < int(dm_build_1313); icol++ {
+		dm_build_1316[icol] = dm_build_1309.dm_build_1114.dm_build_700.Dm_build_508()
+	}
+
+	for icol := 0; icol < int(dm_build_1313); icol++ {
+
+		dataCol := icol + 1
+		if dm_build_1314 && icol == dm_build_1311 {
+			dataCol = 0
+		} else if dm_build_1314 && icol > dm_build_1311 {
+			dataCol = icol
+		}
+
+		allNotNull := dm_build_1309.dm_build_1114.dm_build_700.Dm_build_490() == 1
+		var isNull []bool = nil
+		if !allNotNull {
+			isNull = make([]bool, dm_build_1312)
+			for irow := uint32(0); irow < dm_build_1312; irow++ {
+				isNull[irow] = dm_build_1309.dm_build_1114.dm_build_700.Dm_build_484() == 0
+			}
+		}
+
+		for irow := uint32(0); irow < dm_build_1312; irow++ {
+			if allNotNull || !isNull[irow] {
+				dm_build_1317[irow][dataCol] = dm_build_1309.dm_build_1318(int(dm_build_1315[icol]))
+			}
+		}
+	}
+
+	if !dm_build_1314 && dm_build_1311 >= 0 {
+		for irow := uint32(0); irow < dm_build_1312; irow++ {
+			dm_build_1317[irow][0] = dm_build_1317[irow][dm_build_1311+1]
+		}
+	}
+
+	return dm_build_1317
+}
+
+func (dm_build_1319 *dm_build_1221) dm_build_1318(dm_build_1320 int) []byte {
+
+	dm_build_1321 := dm_build_1319.dm_build_1324(dm_build_1320)
+
+	dm_build_1322 := int32(0)
+	if dm_build_1321 == Dm_build_1306 {
+		dm_build_1322 = dm_build_1319.dm_build_1114.dm_build_700.Dm_build_490()
+		dm_build_1321 = int(dm_build_1319.dm_build_1114.dm_build_700.Dm_build_490())
+	} else if dm_build_1321 == Dm_build_1307 {
+		dm_build_1321 = int(dm_build_1319.dm_build_1114.dm_build_700.Dm_build_490())
+	}
+
+	dm_build_1323 := dm_build_1319.dm_build_1114.dm_build_700.Dm_build_511(dm_build_1321 + int(dm_build_1322))
+	if dm_build_1322 == 0 {
+		return dm_build_1323
+	}
+
+	for i := dm_build_1321; i < len(dm_build_1323); i++ {
+		dm_build_1323[i] = ' '
+	}
+	return dm_build_1323
+}
+
+func (dm_build_1325 *dm_build_1221) dm_build_1324(dm_build_1326 int) int {
+
+	dm_build_1327 := 0
+	switch dm_build_1326 {
+	case INT, BIT, TINYINT, SMALLINT, BOOLEAN, NULL:
+		dm_build_1327 = 4
+
+	case BIGINT:
+
+		dm_build_1327 = 8
+
+	case CHAR, VARCHAR2, VARCHAR, BINARY, VARBINARY, BLOB, CLOB:
+		dm_build_1327 = Dm_build_1306
+
+	case DECIMAL:
+		dm_build_1327 = Dm_build_1307
+
+	case REAL:
+		dm_build_1327 = 4
+
+	case DOUBLE:
+		dm_build_1327 = 8
+
+	case DATE, TIME, DATETIME, TIME_TZ, DATETIME_TZ:
+		dm_build_1327 = 12
+
+	case DATETIME2, DATETIME2_TZ:
+		dm_build_1327 = 13
+
+	case INTERVAL_YM:
+		dm_build_1327 = 12
+
+	case INTERVAL_DT:
+		dm_build_1327 = 24
+
+	default:
+		dm_build_1327 = 0
+	}
+	return dm_build_1327
+}
+
+const (
+	Dm_build_1328 = Dm_build_1006
+
+	Dm_build_1329 = Dm_build_1328 + DDWORD_SIZE
+
+	Dm_build_1330 = Dm_build_1329 + LINT64_SIZE
+
+	Dm_build_1331 = Dm_build_1330 + USINT_SIZE
+
+	Dm_build_1332 = Dm_build_1006
+
+	Dm_build_1333 = Dm_build_1332 + DDWORD_SIZE
+)
+
+type dm_build_1334 struct {
+	dm_build_1221
+	dm_build_1335 *innerRows
+	dm_build_1336 int64
+	dm_build_1337 int64
+}
+
+func dm_build_1338(dm_build_1339 *dm_build_697, dm_build_1340 *innerRows, dm_build_1341 int64, dm_build_1342 int64) *dm_build_1334 {
+	dm_build_1343 := new(dm_build_1334)
+	dm_build_1343.dm_build_1122(dm_build_1339, Dm_build_984, dm_build_1340.dmStmt)
+	dm_build_1343.dm_build_1335 = dm_build_1340
+	dm_build_1343.dm_build_1336 = dm_build_1341
+	dm_build_1343.dm_build_1337 = dm_build_1342
+	return dm_build_1343
+}
+
+func (dm_build_1345 *dm_build_1334) dm_build_1099() error {
+
+	dm_build_1345.dm_build_1114.dm_build_700.Dm_build_560(Dm_build_1328, dm_build_1345.dm_build_1336)
+
+	dm_build_1345.dm_build_1114.dm_build_700.Dm_build_560(Dm_build_1329, dm_build_1345.dm_build_1337)
+
+	dm_build_1345.dm_build_1114.dm_build_700.Dm_build_552(Dm_build_1330, dm_build_1345.dm_build_1335.id)
+
+	dm_build_1346 := dm_build_1345.dm_build_1335.dmStmt.dmConn.dmConnector.bufPrefetch
+	var dm_build_1347 int32
+	if dm_build_1345.dm_build_1335.sizeOfRow != 0 && dm_build_1345.dm_build_1335.fetchSize != 0 {
+		if dm_build_1345.dm_build_1335.sizeOfRow*dm_build_1345.dm_build_1335.fetchSize > int(INT32_MAX) {
+			dm_build_1347 = INT32_MAX
+		} else {
+			dm_build_1347 = int32(dm_build_1345.dm_build_1335.sizeOfRow * dm_build_1345.dm_build_1335.fetchSize)
+		}
+
+		if dm_build_1347 < Dm_build_1038 {
+			dm_build_1346 = int(Dm_build_1038)
+		} else if dm_build_1347 > Dm_build_1039 {
+			dm_build_1346 = int(Dm_build_1039)
+		} else {
+			dm_build_1346 = int(dm_build_1347)
+		}
+
+		dm_build_1345.dm_build_1114.dm_build_700.Dm_build_556(Dm_build_1331, int32(dm_build_1346))
+	}
+
+	return nil
+}
+
+func (dm_build_1349 *dm_build_1334) dm_build_1103() (interface{}, error) {
+	dm_build_1350 := execRetInfo{}
+	dm_build_1350.rsBdta = dm_build_1349.dm_build_1335.isBdta
+
+	dm_build_1350.updateCount = dm_build_1349.dm_build_1114.dm_build_700.Dm_build_637(Dm_build_1332)
+	dm_build_1351 := dm_build_1349.dm_build_1114.dm_build_700.Dm_build_634(Dm_build_1333)
+
+	dm_build_1349.dm_build_1284(&dm_build_1350, len(dm_build_1349.dm_build_1335.columns), int(dm_build_1351), -1)
+
+	return &dm_build_1350, nil
+}
+
+type dm_build_1352 struct {
+	dm_build_1113
+	dm_build_1353 *lob
+	dm_build_1354 int
+	dm_build_1355 int
+}
+
+func dm_build_1356(dm_build_1357 *dm_build_697, dm_build_1358 *lob, dm_build_1359 int, dm_build_1360 int) *dm_build_1352 {
+	dm_build_1361 := new(dm_build_1352)
+	dm_build_1361.dm_build_1118(dm_build_1357, Dm_build_997)
+	dm_build_1361.dm_build_1353 = dm_build_1358
+	dm_build_1361.dm_build_1354 = dm_build_1359
+	dm_build_1361.dm_build_1355 = dm_build_1360
+	return dm_build_1361
+}
+
+func (dm_build_1363 *dm_build_1352) dm_build_1099() error {
+
+	dm_build_1363.dm_build_1114.dm_build_700.Dm_build_404(byte(dm_build_1363.dm_build_1353.lobFlag))
+
+	dm_build_1363.dm_build_1114.dm_build_700.Dm_build_416(dm_build_1363.dm_build_1353.tabId)
+
+	dm_build_1363.dm_build_1114.dm_build_700.Dm_build_412(dm_build_1363.dm_build_1353.colId)
+
+	dm_build_1363.dm_build_1114.dm_build_700.Dm_build_432(uint64(dm_build_1363.dm_build_1353.blobId))
+
+	dm_build_1363.dm_build_1114.dm_build_700.Dm_build_412(dm_build_1363.dm_build_1353.groupId)
+
+	dm_build_1363.dm_build_1114.dm_build_700.Dm_build_412(dm_build_1363.dm_build_1353.fileId)
+
+	dm_build_1363.dm_build_1114.dm_build_700.Dm_build_416(dm_build_1363.dm_build_1353.pageNo)
+
+	dm_build_1363.dm_build_1114.dm_build_700.Dm_build_412(dm_build_1363.dm_build_1353.curFileId)
+
+	dm_build_1363.dm_build_1114.dm_build_700.Dm_build_416(dm_build_1363.dm_build_1353.curPageNo)
+
+	dm_build_1363.dm_build_1114.dm_build_700.Dm_build_416(dm_build_1363.dm_build_1353.totalOffset)
+
+	dm_build_1363.dm_build_1114.dm_build_700.Dm_build_416(int32(dm_build_1363.dm_build_1354))
+
+	dm_build_1363.dm_build_1114.dm_build_700.Dm_build_416(int32(dm_build_1363.dm_build_1355))
+
+	if dm_build_1363.dm_build_1114.dm_build_701.NewLobFlag {
+		dm_build_1363.dm_build_1114.dm_build_700.Dm_build_432(uint64(dm_build_1363.dm_build_1353.rowId))
+		dm_build_1363.dm_build_1114.dm_build_700.Dm_build_412(dm_build_1363.dm_build_1353.exGroupId)
+		dm_build_1363.dm_build_1114.dm_build_700.Dm_build_412(dm_build_1363.dm_build_1353.exFileId)
+		dm_build_1363.dm_build_1114.dm_build_700.Dm_build_416(dm_build_1363.dm_build_1353.exPageNo)
+	}
+
+	return nil
+}
+
+func (dm_build_1365 *dm_build_1352) dm_build_1103() (interface{}, error) {
+
+	dm_build_1365.dm_build_1353.readOver = dm_build_1365.dm_build_1114.dm_build_700.Dm_build_484() == 1
+	var dm_build_1366 = dm_build_1365.dm_build_1114.dm_build_700.Dm_build_508()
+	if dm_build_1366 <= 0 {
+		return []byte(nil), nil
+	}
+	dm_build_1365.dm_build_1353.curFileId = dm_build_1365.dm_build_1114.dm_build_700.Dm_build_487()
+	dm_build_1365.dm_build_1353.curPageNo = dm_build_1365.dm_build_1114.dm_build_700.Dm_build_490()
+	dm_build_1365.dm_build_1353.totalOffset = dm_build_1365.dm_build_1114.dm_build_700.Dm_build_490()
+
+	return dm_build_1365.dm_build_1114.dm_build_700.Dm_build_521(int(dm_build_1366)), nil
+}
+
+type dm_build_1367 struct {
+	dm_build_1113
+	dm_build_1368 *lob
+}
+
+func dm_build_1369(dm_build_1370 *dm_build_697, dm_build_1371 *lob) *dm_build_1367 {
+	dm_build_1372 := new(dm_build_1367)
+	dm_build_1372.dm_build_1118(dm_build_1370, Dm_build_994)
+	dm_build_1372.dm_build_1368 = dm_build_1371
+	return dm_build_1372
+}
+
+func (dm_build_1374 *dm_build_1367) dm_build_1099() error {
+
+	dm_build_1374.dm_build_1114.dm_build_700.Dm_build_404(byte(dm_build_1374.dm_build_1368.lobFlag))
+
+	dm_build_1374.dm_build_1114.dm_build_700.Dm_build_432(uint64(dm_build_1374.dm_build_1368.blobId))
+
+	dm_build_1374.dm_build_1114.dm_build_700.Dm_build_412(dm_build_1374.dm_build_1368.groupId)
+
+	dm_build_1374.dm_build_1114.dm_build_700.Dm_build_412(dm_build_1374.dm_build_1368.fileId)
+
+	dm_build_1374.dm_build_1114.dm_build_700.Dm_build_416(dm_build_1374.dm_build_1368.pageNo)
+
+	if dm_build_1374.dm_build_1114.dm_build_701.NewLobFlag {
+		dm_build_1374.dm_build_1114.dm_build_700.Dm_build_416(dm_build_1374.dm_build_1368.tabId)
+		dm_build_1374.dm_build_1114.dm_build_700.Dm_build_412(dm_build_1374.dm_build_1368.colId)
+		dm_build_1374.dm_build_1114.dm_build_700.Dm_build_432(uint64(dm_build_1374.dm_build_1368.rowId))
+
+		dm_build_1374.dm_build_1114.dm_build_700.Dm_build_412(dm_build_1374.dm_build_1368.exGroupId)
+		dm_build_1374.dm_build_1114.dm_build_700.Dm_build_412(dm_build_1374.dm_build_1368.exFileId)
+		dm_build_1374.dm_build_1114.dm_build_700.Dm_build_416(dm_build_1374.dm_build_1368.exPageNo)
+	}
+
+	return nil
+}
+
+func (dm_build_1376 *dm_build_1367) dm_build_1103() (interface{}, error) {
+
+	if dm_build_1376.dm_build_1114.dm_build_700.Dm_build_383(false) == 8 {
+		return dm_build_1376.dm_build_1114.dm_build_700.Dm_build_493(), nil
+	} else {
+		return int64(dm_build_1376.dm_build_1114.dm_build_700.Dm_build_508()), nil
+	}
+}
+
+type dm_build_1377 struct {
+	dm_build_1113
+	dm_build_1378 *lob
+	dm_build_1379 int
+}
+
+func dm_build_1380(dm_build_1381 *dm_build_697, dm_build_1382 *lob, dm_build_1383 int) *dm_build_1377 {
+	dm_build_1384 := new(dm_build_1377)
+	dm_build_1384.dm_build_1118(dm_build_1381, Dm_build_996)
+	dm_build_1384.dm_build_1378 = dm_build_1382
+	dm_build_1384.dm_build_1379 = dm_build_1383
+	return dm_build_1384
+}
+
+func (dm_build_1386 *dm_build_1377) dm_build_1099() error {
+
+	dm_build_1386.dm_build_1114.dm_build_700.Dm_build_404(byte(dm_build_1386.dm_build_1378.lobFlag))
+
+	dm_build_1386.dm_build_1114.dm_build_700.Dm_build_432(uint64(dm_build_1386.dm_build_1378.blobId))
+
+	dm_build_1386.dm_build_1114.dm_build_700.Dm_build_412(dm_build_1386.dm_build_1378.groupId)
+
+	dm_build_1386.dm_build_1114.dm_build_700.Dm_build_412(dm_build_1386.dm_build_1378.fileId)
+
+	dm_build_1386.dm_build_1114.dm_build_700.Dm_build_416(dm_build_1386.dm_build_1378.pageNo)
+
+	dm_build_1386.dm_build_1114.dm_build_700.Dm_build_416(dm_build_1386.dm_build_1378.tabId)
+	dm_build_1386.dm_build_1114.dm_build_700.Dm_build_412(dm_build_1386.dm_build_1378.colId)
+	dm_build_1386.dm_build_1114.dm_build_700.Dm_build_432(uint64(dm_build_1386.dm_build_1378.rowId))
+	dm_build_1386.dm_build_1114.dm_build_700.Dm_build_444(Dm_build_1.Dm_build_206(uint32(dm_build_1386.dm_build_1379)))
+
+	if dm_build_1386.dm_build_1114.dm_build_701.NewLobFlag {
+		dm_build_1386.dm_build_1114.dm_build_700.Dm_build_412(dm_build_1386.dm_build_1378.exGroupId)
+		dm_build_1386.dm_build_1114.dm_build_700.Dm_build_412(dm_build_1386.dm_build_1378.exFileId)
+		dm_build_1386.dm_build_1114.dm_build_700.Dm_build_416(dm_build_1386.dm_build_1378.exPageNo)
+	}
+	return nil
+}
+
+func (dm_build_1388 *dm_build_1377) dm_build_1103() (interface{}, error) {
+
+	dm_build_1389 := dm_build_1388.dm_build_1114.dm_build_700.Dm_build_508()
+	dm_build_1388.dm_build_1378.blobId = dm_build_1388.dm_build_1114.dm_build_700.Dm_build_493()
+	dm_build_1388.dm_build_1378.resetCurrentInfo()
+	return int64(dm_build_1389), nil
+}
+
+const (
+	Dm_build_1390 = Dm_build_1006
+
+	Dm_build_1391 = Dm_build_1390 + ULINT_SIZE
+
+	Dm_build_1392 = Dm_build_1391 + ULINT_SIZE
+
+	Dm_build_1393 = Dm_build_1392 + ULINT_SIZE
+
+	Dm_build_1394 = Dm_build_1393 + BYTE_SIZE
+
+	Dm_build_1395 = Dm_build_1394 + USINT_SIZE
+
+	Dm_build_1396 = Dm_build_1395 + ULINT_SIZE
+
+	Dm_build_1397 = Dm_build_1396 + BYTE_SIZE
+
+	Dm_build_1398 = Dm_build_1397 + BYTE_SIZE
+
+	Dm_build_1399 = Dm_build_1398 + BYTE_SIZE
+
+	Dm_build_1400 = Dm_build_1006
+
+	Dm_build_1401 = Dm_build_1400 + ULINT_SIZE
+
+	Dm_build_1402 = Dm_build_1401 + ULINT_SIZE
+
+	Dm_build_1403 = Dm_build_1402 + BYTE_SIZE
+
+	Dm_build_1404 = Dm_build_1403 + ULINT_SIZE
+
+	Dm_build_1405 = Dm_build_1404 + BYTE_SIZE
+
+	Dm_build_1406 = Dm_build_1405 + BYTE_SIZE
+
+	Dm_build_1407 = Dm_build_1406 + USINT_SIZE
+
+	Dm_build_1408 = Dm_build_1407 + USINT_SIZE
+
+	Dm_build_1409 = Dm_build_1408 + BYTE_SIZE
+
+	Dm_build_1410 = Dm_build_1409 + USINT_SIZE
+
+	Dm_build_1411 = Dm_build_1410 + BYTE_SIZE
+
+	Dm_build_1412 = Dm_build_1411 + BYTE_SIZE
+
+	Dm_build_1413 = Dm_build_1412 + ULINT_SIZE
+
+	Dm_build_1414 = Dm_build_1413 + USINT_SIZE
+)
+
+type dm_build_1415 struct {
+	dm_build_1113
+
+	dm_build_1416 *DmConnection
+
+	dm_build_1417 bool
+}
+
+func dm_build_1418(dm_build_1419 *dm_build_697) *dm_build_1415 {
+	dm_build_1420 := new(dm_build_1415)
+	dm_build_1420.dm_build_1118(dm_build_1419, Dm_build_978)
+	dm_build_1420.dm_build_1416 = dm_build_1419.dm_build_701
+	return dm_build_1420
+}
+
+func (dm_build_1422 *dm_build_1415) dm_build_1099() error {
+
+	if dm_build_1422.dm_build_1416.dmConnector.newClientType {
+		dm_build_1422.dm_build_1114.dm_build_700.Dm_build_556(Dm_build_1390, Dm_build_1017)
+	} else {
+		dm_build_1422.dm_build_1114.dm_build_700.Dm_build_556(Dm_build_1390, Dm_build_1016)
+	}
+
+	dm_build_1422.dm_build_1114.dm_build_700.Dm_build_556(Dm_build_1391, g2dbIsoLevel(dm_build_1422.dm_build_1416.IsoLevel))
+	dm_build_1422.dm_build_1114.dm_build_700.Dm_build_556(Dm_build_1392, int32(Locale))
+	dm_build_1422.dm_build_1114.dm_build_700.Dm_build_552(Dm_build_1394, dm_build_1422.dm_build_1416.dmConnector.localTimezone)
+
+	if dm_build_1422.dm_build_1416.ReadOnly {
+		dm_build_1422.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1393, Dm_build_1041)
+	} else {
+		dm_build_1422.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1393, Dm_build_1040)
+	}
+
+	dm_build_1422.dm_build_1114.dm_build_700.Dm_build_556(Dm_build_1395, int32(dm_build_1422.dm_build_1416.dmConnector.sessionTimeout))
+
+	if dm_build_1422.dm_build_1416.dmConnector.mppLocal {
+		dm_build_1422.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1396, 1)
+	} else {
+		dm_build_1422.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1396, 0)
+	}
+
+	if dm_build_1422.dm_build_1416.dmConnector.rwSeparate {
+		dm_build_1422.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1397, 1)
+	} else {
+		dm_build_1422.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1397, 0)
+	}
+
+	if dm_build_1422.dm_build_1416.NewLobFlag {
+		dm_build_1422.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1398, 1)
+	} else {
+		dm_build_1422.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1398, 0)
+	}
+
+	dm_build_1422.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1399, dm_build_1422.dm_build_1416.dmConnector.osAuthType)
+
+	dm_build_1423 := dm_build_1422.dm_build_1416.getServerEncoding()
+
+	if dm_build_1422.dm_build_1114.dm_build_707 != "" {
+
+	}
+
+	dm_build_1424 := Dm_build_1.Dm_build_217(dm_build_1422.dm_build_1416.dmConnector.user, dm_build_1423, dm_build_1422.dm_build_1114.dm_build_701)
+	dm_build_1425 := Dm_build_1.Dm_build_217(dm_build_1422.dm_build_1416.dmConnector.password, dm_build_1423, dm_build_1422.dm_build_1114.dm_build_701)
+	if len(dm_build_1424) > Dm_build_1014 {
+		return ECGO_USERNAME_TOO_LONG.throw()
+	}
+	if len(dm_build_1425) > Dm_build_1014 {
+		return ECGO_PASSWORD_TOO_LONG.throw()
+	}
+
+	if dm_build_1422.dm_build_1114.dm_build_703 && dm_build_1422.dm_build_1416.dmConnector.loginCertificate != "" {
+
+	} else if dm_build_1422.dm_build_1114.dm_build_703 {
+		dm_build_1424 = dm_build_1422.dm_build_1114.dm_build_702.Encrypt(dm_build_1424, false)
+		dm_build_1425 = dm_build_1422.dm_build_1114.dm_build_702.Encrypt(dm_build_1425, false)
+	}
+
+	dm_build_1422.dm_build_1114.dm_build_700.Dm_build_448(dm_build_1424)
+	dm_build_1422.dm_build_1114.dm_build_700.Dm_build_448(dm_build_1425)
+
+	dm_build_1422.dm_build_1114.dm_build_700.Dm_build_460(dm_build_1422.dm_build_1416.dmConnector.appName, dm_build_1423, dm_build_1422.dm_build_1114.dm_build_701)
+	dm_build_1422.dm_build_1114.dm_build_700.Dm_build_460(dm_build_1422.dm_build_1416.dmConnector.osName, dm_build_1423, dm_build_1422.dm_build_1114.dm_build_701)
+
+	if hostName, err := os.Hostname(); err != nil {
+		dm_build_1422.dm_build_1114.dm_build_700.Dm_build_460(hostName, dm_build_1423, dm_build_1422.dm_build_1114.dm_build_701)
+	} else {
+		dm_build_1422.dm_build_1114.dm_build_700.Dm_build_460("", dm_build_1423, dm_build_1422.dm_build_1114.dm_build_701)
+	}
+
+	if dm_build_1422.dm_build_1416.dmConnector.rwStandby {
+		dm_build_1422.dm_build_1114.dm_build_700.Dm_build_404(1)
+	} else {
+		dm_build_1422.dm_build_1114.dm_build_700.Dm_build_404(0)
+	}
+
+	return nil
+}
+
+func (dm_build_1427 *dm_build_1415) dm_build_1103() (interface{}, error) {
+
+	dm_build_1427.dm_build_1416.MaxRowSize = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_634(Dm_build_1400)
+	dm_build_1427.dm_build_1416.DDLAutoCommit = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_628(Dm_build_1402) == 1
+	dm_build_1427.dm_build_1416.IsoLevel = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_634(Dm_build_1403)
+	dm_build_1427.dm_build_1416.dmConnector.caseSensitive = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_628(Dm_build_1404) == 1
+	dm_build_1427.dm_build_1416.BackslashEscape = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_628(Dm_build_1405) == 1
+	dm_build_1427.dm_build_1416.SvrStat = int32(dm_build_1427.dm_build_1114.dm_build_700.Dm_build_631(Dm_build_1407))
+	dm_build_1427.dm_build_1416.SvrMode = int32(dm_build_1427.dm_build_1114.dm_build_700.Dm_build_631(Dm_build_1406))
+	dm_build_1427.dm_build_1416.ConstParaOpt = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_628(Dm_build_1408) == 1
+	dm_build_1427.dm_build_1416.DbTimezone = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_631(Dm_build_1409)
+	dm_build_1427.dm_build_1416.NewLobFlag = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_628(Dm_build_1411) == 1
+
+	if dm_build_1427.dm_build_1416.dmConnector.bufPrefetch == 0 {
+		dm_build_1427.dm_build_1416.dmConnector.bufPrefetch = int(dm_build_1427.dm_build_1114.dm_build_700.Dm_build_634(Dm_build_1412))
+	}
+
+	dm_build_1427.dm_build_1416.LifeTimeRemainder = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_631(Dm_build_1413)
+	dm_build_1427.dm_build_1416.dscControl = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_628(Dm_build_1414) == 1
+
+	dm_build_1428 := dm_build_1427.dm_build_1416.getServerEncoding()
+
+	dm_build_1427.dm_build_1416.InstanceName = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_532(dm_build_1428, dm_build_1427.dm_build_1114.dm_build_701)
+
+	var dm_build_1429 = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_490()
+	if dm_build_1429 == 0 && dm_build_1427.dm_build_1416.MsgVersion > 0 {
+		dm_build_1427.dm_build_1416.Schema = strings.ToUpper(dm_build_1427.dm_build_1416.dmConnector.user)
+	} else {
+		dm_build_1427.dm_build_1416.Schema = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_527(int(dm_build_1429), dm_build_1428, dm_build_1427.dm_build_1114.dm_build_701)
+	}
+
+	dm_build_1427.dm_build_1416.LastLoginIP = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_532(dm_build_1428, dm_build_1427.dm_build_1114.dm_build_701)
+	dm_build_1427.dm_build_1416.LastLoginTime = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_532(dm_build_1428, dm_build_1427.dm_build_1114.dm_build_701)
+	dm_build_1427.dm_build_1416.FailedAttempts = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_490()
+	dm_build_1427.dm_build_1416.LoginWarningID = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_490()
+	dm_build_1427.dm_build_1416.GraceTimeRemainder = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_490()
+	dm_build_1427.dm_build_1416.Guid = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_532(dm_build_1428, dm_build_1427.dm_build_1114.dm_build_701)
+	dm_build_1427.dm_build_1416.DbName = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_532(dm_build_1428, dm_build_1427.dm_build_1114.dm_build_701)
+
+	if dm_build_1427.dm_build_1114.dm_build_700.Dm_build_628(Dm_build_1410) == 1 {
+		dm_build_1427.dm_build_1416.StandbyHost = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_532(dm_build_1428, dm_build_1427.dm_build_1114.dm_build_701)
+		dm_build_1427.dm_build_1416.StandbyPort = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_490()
+		dm_build_1427.dm_build_1416.StandbyCount = int32(dm_build_1427.dm_build_1114.dm_build_700.Dm_build_505())
+	}
+
+	if dm_build_1427.dm_build_1114.dm_build_700.Dm_build_383(false) > 0 {
+		dm_build_1427.dm_build_1416.SessionID = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_493()
+	}
+
+	if dm_build_1427.dm_build_1114.dm_build_700.Dm_build_383(false) > 0 {
+		if dm_build_1427.dm_build_1114.dm_build_700.Dm_build_484() == 1 {
+
+			dm_build_1427.dm_build_1416.FormatDate = "DD-MON-YY"
+
+			dm_build_1427.dm_build_1416.FormatTime = "HH12.MI.SS.FF6 AM"
+
+			dm_build_1427.dm_build_1416.FormatTimestamp = "DD-MON-YY HH12.MI.SS.FF6 AM"
+
+			dm_build_1427.dm_build_1416.FormatTimestampTZ = "DD-MON-YY HH12.MI.SS.FF6 AM +TZH:TZM"
+
+			dm_build_1427.dm_build_1416.FormatTimeTZ = "HH12.MI.SS.FF6 AM +TZH:TZM"
+		}
+	}
+
+	if dm_build_1427.dm_build_1114.dm_build_700.Dm_build_383(false) > 0 {
+
+		format := dm_build_1427.dm_build_1114.dm_build_700.Dm_build_536(dm_build_1428, dm_build_1427.dm_build_1114.dm_build_701)
+		if format != "" {
+			dm_build_1427.dm_build_1416.FormatDate = format
+		}
+		format = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_536(dm_build_1428, dm_build_1427.dm_build_1114.dm_build_701)
+		if format != "" {
+			dm_build_1427.dm_build_1416.FormatTime = format
+		}
+		format = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_536(dm_build_1428, dm_build_1427.dm_build_1114.dm_build_701)
+		if format != "" {
+			dm_build_1427.dm_build_1416.FormatTimestamp = format
+		}
+		format = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_536(dm_build_1428, dm_build_1427.dm_build_1114.dm_build_701)
+		if format != "" {
+			dm_build_1427.dm_build_1416.FormatTimestampTZ = format
+		}
+		format = dm_build_1427.dm_build_1114.dm_build_700.Dm_build_536(dm_build_1428, dm_build_1427.dm_build_1114.dm_build_701)
+		if format != "" {
+			dm_build_1427.dm_build_1416.FormatTimeTZ = format
+		}
+	}
+
+	return nil, nil
+}
+
+const (
+	Dm_build_1430 = Dm_build_1006
+)
+
+type dm_build_1431 struct {
+	dm_build_1221
+	dm_build_1432 int16
+}
+
+func dm_build_1433(dm_build_1434 *dm_build_697, dm_build_1435 *DmStatement, dm_build_1436 int16) *dm_build_1431 {
+	dm_build_1437 := new(dm_build_1431)
+	dm_build_1437.dm_build_1122(dm_build_1434, Dm_build_998, dm_build_1435)
+	dm_build_1437.dm_build_1432 = dm_build_1436
+	return dm_build_1437
+}
+
+func (dm_build_1439 *dm_build_1431) dm_build_1099() error {
+	dm_build_1439.dm_build_1114.dm_build_700.Dm_build_552(Dm_build_1430, dm_build_1439.dm_build_1432)
+	return nil
+}
+
+func (dm_build_1441 *dm_build_1431) dm_build_1103() (interface{}, error) {
+	return dm_build_1441.dm_build_1221.dm_build_1103()
+}
+
+const (
+	Dm_build_1442 = Dm_build_1006
+	Dm_build_1443 = Dm_build_1442 + USINT_SIZE
+)
+
+type dm_build_1444 struct {
+	dm_build_1454
+	dm_build_1445 []parameter
+}
+
+func dm_build_1446(dm_build_1447 *dm_build_697, dm_build_1448 *DmStatement, dm_build_1449 []parameter) *dm_build_1444 {
+	dm_build_1450 := new(dm_build_1444)
+	dm_build_1450.dm_build_1122(dm_build_1447, Dm_build_1002, dm_build_1448)
+	dm_build_1450.dm_build_1445 = dm_build_1449
+	return dm_build_1450
+}
+
+func (dm_build_1452 *dm_build_1444) dm_build_1099() error {
+
+	if dm_build_1452.dm_build_1445 == nil {
+		dm_build_1452.dm_build_1114.dm_build_700.Dm_build_552(Dm_build_1442, 0)
+	} else {
+		dm_build_1452.dm_build_1114.dm_build_700.Dm_build_552(Dm_build_1442, int16(len(dm_build_1452.dm_build_1445)))
+	}
+
+	dm_build_1452.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1443, 0)
+
+	return dm_build_1452.dm_build_1246(dm_build_1452.dm_build_1445)
+}
+
+const Dm_build_1453 = 38
+
+type dm_build_1454 struct {
+	dm_build_1221
+	dm_build_1455 bool
+	dm_build_1456 int16
+}
+
+func dm_build_1457(dm_build_1458 *dm_build_697, dm_build_1459 *DmStatement, dm_build_1460 bool, dm_build_1461 int16) *dm_build_1454 {
+	dm_build_1462 := new(dm_build_1454)
+	dm_build_1462.dm_build_1122(dm_build_1458, Dm_build_982, dm_build_1459)
+	dm_build_1462.dm_build_1455 = dm_build_1460
+	dm_build_1462.dm_build_1456 = dm_build_1461
+	return dm_build_1462
+}
+
+func (dm_build_1464 *dm_build_1454) dm_build_1099() error {
+
+	dm_build_1465 := Dm_build_1006
+
+	if dm_build_1464.dm_build_1114.dm_build_701.autoCommit {
+		dm_build_1465 += dm_build_1464.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1465, 1)
+	} else {
+		dm_build_1465 += dm_build_1464.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1465, 0)
+	}
+
+	if dm_build_1464.dm_build_1455 {
+		dm_build_1465 += dm_build_1464.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1465, 1)
+	} else {
+		dm_build_1465 += dm_build_1464.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1465, 0)
+	}
+
+	dm_build_1465 += dm_build_1464.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1465, 0)
+
+	dm_build_1465 += dm_build_1464.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1465, 1)
+
+	dm_build_1465 += dm_build_1464.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1465, 0)
+
+	dm_build_1465 += dm_build_1464.dm_build_1114.dm_build_700.Dm_build_552(dm_build_1465, Dm_build_1057)
+
+	if dm_build_1464.dm_build_1117.maxRows <= 0 || dm_build_1464.dm_build_1114.dm_build_701.dmConnector.enRsCache {
+		dm_build_1465 += dm_build_1464.dm_build_1114.dm_build_700.Dm_build_560(dm_build_1465, INT64_MAX)
+	} else {
+		dm_build_1465 += dm_build_1464.dm_build_1114.dm_build_700.Dm_build_560(dm_build_1465, dm_build_1464.dm_build_1117.maxRows)
+	}
+
+	if dm_build_1464.dm_build_1114.dm_build_701.dmConnector.isBdtaRS {
+		dm_build_1465 += dm_build_1464.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1465, Dm_build_1085)
+	} else {
+		dm_build_1465 += dm_build_1464.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1465, Dm_build_1084)
+	}
+
+	dm_build_1465 += dm_build_1464.dm_build_1114.dm_build_700.Dm_build_552(dm_build_1465, 0)
+
+	dm_build_1465 += dm_build_1464.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1465, 1)
+
+	dm_build_1465 += dm_build_1464.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1465, 0)
+
+	dm_build_1465 += dm_build_1464.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1465, 0)
+
+	dm_build_1465 += dm_build_1464.dm_build_1114.dm_build_700.Dm_build_556(dm_build_1465, dm_build_1464.dm_build_1117.queryTimeout)
+
+	if dm_build_1464.dm_build_1117.innerExec {
+		dm_build_1465 += dm_build_1464.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1465, 1)
+	} else {
+		dm_build_1465 += dm_build_1464.dm_build_1114.dm_build_700.Dm_build_548(dm_build_1465, 0)
+	}
+
+	if dm_build_1464.dm_build_1114.dm_build_701.MsgVersion >= Dm_build_970 {
+		if dm_build_1464.dm_build_1455 {
+			dm_build_1464.dm_build_1224 = dm_build_1464.dm_build_1252()
+		} else {
+			dm_build_1464.dm_build_1224 = Dm_build_1215
+		}
+		dm_build_1464.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1453, byte(dm_build_1464.dm_build_1224))
+	}
+
+	dm_build_1464.dm_build_1114.dm_build_700.Dm_build_478(dm_build_1464.dm_build_1117.nativeSql, dm_build_1464.dm_build_1114.dm_build_701.getServerEncoding(), dm_build_1464.dm_build_1114.dm_build_701)
+
+	return nil
+}
+
+func (dm_build_1467 *dm_build_1454) dm_build_1103() (interface{}, error) {
+
+	if dm_build_1467.dm_build_1455 {
+		return dm_build_1467.dm_build_1221.dm_build_1103()
+	}
+
+	dm_build_1468 := NewExceInfo()
+	dm_build_1469 := Dm_build_1006
+
+	dm_build_1468.retSqlType = dm_build_1467.dm_build_1114.dm_build_700.Dm_build_631(dm_build_1469)
+	dm_build_1469 += USINT_SIZE
+
+	dm_build_1470 := dm_build_1467.dm_build_1114.dm_build_700.Dm_build_649(dm_build_1469)
+	dm_build_1469 += USINT_SIZE
+
+	dm_build_1471 := dm_build_1467.dm_build_1114.dm_build_700.Dm_build_631(dm_build_1469)
+	dm_build_1469 += USINT_SIZE
+
+	dm_build_1467.dm_build_1114.dm_build_700.Dm_build_637(dm_build_1469)
+	dm_build_1469 += DDWORD_SIZE
+
+	dm_build_1467.dm_build_1114.dm_build_701.TrxStatus = dm_build_1467.dm_build_1114.dm_build_700.Dm_build_634(dm_build_1469)
+	dm_build_1469 += ULINT_SIZE
+
+	if dm_build_1470 > 0 {
+		dm_build_1467.dm_build_1117.serverParams = dm_build_1467.dm_build_1472(int(dm_build_1470))
+		dm_build_1467.dm_build_1117.bindParams = make([]parameter, dm_build_1470)
+		for i := 0; i < int(dm_build_1470); i++ {
+			dm_build_1467.dm_build_1117.bindParams[i].InitParameter()
+			dm_build_1467.dm_build_1117.bindParams[i].colType = dm_build_1467.dm_build_1117.serverParams[i].colType
+			dm_build_1467.dm_build_1117.bindParams[i].prec = dm_build_1467.dm_build_1117.serverParams[i].prec
+			dm_build_1467.dm_build_1117.bindParams[i].scale = dm_build_1467.dm_build_1117.serverParams[i].scale
+			dm_build_1467.dm_build_1117.bindParams[i].nullable = dm_build_1467.dm_build_1117.serverParams[i].nullable
+			dm_build_1467.dm_build_1117.bindParams[i].hasDefault = dm_build_1467.dm_build_1117.serverParams[i].hasDefault
+			dm_build_1467.dm_build_1117.bindParams[i].typeFlag = dm_build_1467.dm_build_1117.serverParams[i].typeFlag
+			dm_build_1467.dm_build_1117.bindParams[i].lob = dm_build_1467.dm_build_1117.serverParams[i].lob
+			dm_build_1467.dm_build_1117.bindParams[i].ioType = dm_build_1467.dm_build_1117.serverParams[i].ioType
+			dm_build_1467.dm_build_1117.bindParams[i].name = dm_build_1467.dm_build_1117.serverParams[i].name
+			dm_build_1467.dm_build_1117.bindParams[i].typeName = dm_build_1467.dm_build_1117.serverParams[i].typeName
+			dm_build_1467.dm_build_1117.bindParams[i].tableName = dm_build_1467.dm_build_1117.serverParams[i].tableName
+			dm_build_1467.dm_build_1117.bindParams[i].schemaName = dm_build_1467.dm_build_1117.serverParams[i].schemaName
+			dm_build_1467.dm_build_1117.bindParams[i].lobTabId = dm_build_1467.dm_build_1117.serverParams[i].lobTabId
+			dm_build_1467.dm_build_1117.bindParams[i].lobColId = dm_build_1467.dm_build_1117.serverParams[i].lobColId
+			dm_build_1467.dm_build_1117.bindParams[i].mask = dm_build_1467.dm_build_1117.serverParams[i].mask
+			dm_build_1467.dm_build_1117.bindParams[i].typeDescriptor = dm_build_1467.dm_build_1117.serverParams[i].typeDescriptor
+		}
+
+		dm_build_1467.dm_build_1117.paramCount = int32(dm_build_1470)
+	} else {
+		dm_build_1467.dm_build_1117.serverParams = make([]parameter, 0)
+		dm_build_1467.dm_build_1117.bindParams = make([]parameter, 0)
+		dm_build_1467.dm_build_1117.paramCount = 0
+	}
+
+	if dm_build_1471 > 0 {
+		dm_build_1467.dm_build_1117.columns = dm_build_1467.dm_build_1274(int(dm_build_1471), dm_build_1468.rsBdta)
+	} else {
+		dm_build_1467.dm_build_1117.columns = make([]column, 0)
+	}
+
+	return dm_build_1468, nil
+}
+
+func (dm_build_1473 *dm_build_1454) dm_build_1472(dm_build_1474 int) []parameter {
+
+	var dm_build_1475, dm_build_1476, dm_build_1477, dm_build_1478 int16
+
+	dm_build_1479 := make([]parameter, dm_build_1474)
+	for i := 0; i < dm_build_1474; i++ {
+
+		dm_build_1479[i].InitParameter()
+
+		dm_build_1479[i].colType = dm_build_1473.dm_build_1114.dm_build_700.Dm_build_490()
+
+		dm_build_1479[i].prec = dm_build_1473.dm_build_1114.dm_build_700.Dm_build_490()
+
+		dm_build_1479[i].scale = dm_build_1473.dm_build_1114.dm_build_700.Dm_build_490()
+
+		dm_build_1479[i].nullable = dm_build_1473.dm_build_1114.dm_build_700.Dm_build_490() != 0
+
+		itemFlag := dm_build_1473.dm_build_1114.dm_build_700.Dm_build_487()
+
+		dm_build_1479[i].hasDefault = int(itemFlag)&Dm_build_1214 != 0
+
+		if int(itemFlag)&Dm_build_1213 != 0 {
+			dm_build_1479[i].typeFlag = TYPE_FLAG_RECOMMEND
+		} else {
+			dm_build_1479[i].typeFlag = TYPE_FLAG_EXACT
+		}
+
+		dm_build_1479[i].lob = int(itemFlag)&Dm_build_1211 != 0
+
+		dm_build_1473.dm_build_1114.dm_build_700.Dm_build_490()
+
+		dm_build_1479[i].ioType = int8(dm_build_1473.dm_build_1114.dm_build_700.Dm_build_487())
+
+		dm_build_1475 = dm_build_1473.dm_build_1114.dm_build_700.Dm_build_487()
+
+		dm_build_1476 = dm_build_1473.dm_build_1114.dm_build_700.Dm_build_487()
+
+		dm_build_1477 = dm_build_1473.dm_build_1114.dm_build_700.Dm_build_487()
+
+		dm_build_1478 = dm_build_1473.dm_build_1114.dm_build_700.Dm_build_487()
+		dm_build_1479[i].name = dm_build_1473.dm_build_1114.dm_build_700.Dm_build_527(int(dm_build_1475), dm_build_1473.dm_build_1114.dm_build_701.getServerEncoding(), dm_build_1473.dm_build_1114.dm_build_701)
+		dm_build_1479[i].typeName = dm_build_1473.dm_build_1114.dm_build_700.Dm_build_527(int(dm_build_1476), dm_build_1473.dm_build_1114.dm_build_701.getServerEncoding(), dm_build_1473.dm_build_1114.dm_build_701)
+		dm_build_1479[i].tableName = dm_build_1473.dm_build_1114.dm_build_700.Dm_build_527(int(dm_build_1477), dm_build_1473.dm_build_1114.dm_build_701.getServerEncoding(), dm_build_1473.dm_build_1114.dm_build_701)
+		dm_build_1479[i].schemaName = dm_build_1473.dm_build_1114.dm_build_700.Dm_build_527(int(dm_build_1478), dm_build_1473.dm_build_1114.dm_build_701.getServerEncoding(), dm_build_1473.dm_build_1114.dm_build_701)
+
+		if dm_build_1479[i].lob {
+			dm_build_1479[i].lobTabId = dm_build_1473.dm_build_1114.dm_build_700.Dm_build_490()
+			dm_build_1479[i].lobColId = dm_build_1473.dm_build_1114.dm_build_700.Dm_build_487()
+		}
+
+		if dm_build_1479[i].colType == DATETIME || dm_build_1479[i].colType == DATETIME2 {
+			if (dm_build_1479[i].scale & LOCAL_DATETIME_SCALE_MASK) != 0 {
+
+				dm_build_1479[i].scale = dm_build_1479[i].scale & ^LOCAL_DATETIME_SCALE_MASK
+				dm_build_1479[i].mask = MASK_LOCAL_DATETIME
+			} else if (dm_build_1479[i].scale & ORACLE_DATE_SCALE_MASK) != 0 {
+
+				dm_build_1479[i].scale = dm_build_1479[i].scale & ^ORACLE_DATE_SCALE_MASK
+				dm_build_1479[i].mask = MASK_ORACLE_DATE
+			}
+		}
+
+		if dm_build_1479[i].colType == DECIMAL && dm_build_1479[i].scale == ORACLE_FLOAT_SCALE_MASK {
+			dm_build_1479[i].prec = int32(math.Round(float64(dm_build_1479[i].prec)*0.30103) + 1)
+			dm_build_1479[i].scale = -1
+			dm_build_1479[i].mask = MASK_ORACLE_FLOAT
+		}
+
+		if dm_build_1479[i].colType == VARCHAR && dm_build_1479[i].prec == BFILE_PREC && dm_build_1479[i].scale == BFILE_SCALE {
+			dm_build_1479[i].mask = MASK_BFILE
+		}
+	}
+
+	for i := 0; i < dm_build_1474; i++ {
+
+		if isComplexType(int(dm_build_1479[i].colType), int(dm_build_1479[i].scale)) {
+
+			strDesc := newTypeDescriptor(dm_build_1473.dm_build_1114.dm_build_701)
+			strDesc.unpack(dm_build_1473.dm_build_1114.dm_build_700)
+			dm_build_1479[i].typeDescriptor = strDesc
+		}
+	}
+
+	return dm_build_1479
+}
+
+const (
+	Dm_build_1480 = Dm_build_1006
+)
+
+type dm_build_1481 struct {
+	dm_build_1113
+	dm_build_1482 int16
+	dm_build_1483 *Dm_build_283
+	dm_build_1484 int32
+}
+
+func dm_build_1485(dm_build_1486 *dm_build_697, dm_build_1487 *DmStatement, dm_build_1488 int16, dm_build_1489 *Dm_build_283, dm_build_1490 int32) *dm_build_1481 {
+	dm_build_1491 := new(dm_build_1481)
+	dm_build_1491.dm_build_1122(dm_build_1486, Dm_build_988, dm_build_1487)
+	dm_build_1491.dm_build_1482 = dm_build_1488
+	dm_build_1491.dm_build_1483 = dm_build_1489
+	dm_build_1491.dm_build_1484 = dm_build_1490
+	return dm_build_1491
+}
+
+func (dm_build_1493 *dm_build_1481) dm_build_1099() error {
+	dm_build_1493.dm_build_1114.dm_build_700.Dm_build_552(Dm_build_1480, dm_build_1493.dm_build_1482)
+
+	dm_build_1493.dm_build_1114.dm_build_700.Dm_build_416(dm_build_1493.dm_build_1484)
+
+	if dm_build_1493.dm_build_1114.dm_build_701.NewLobFlag {
+		dm_build_1493.dm_build_1114.dm_build_700.Dm_build_416(-1)
+	}
+	dm_build_1493.dm_build_1483.Dm_build_290(dm_build_1493.dm_build_1114.dm_build_700, int(dm_build_1493.dm_build_1484))
+	return nil
+}
+
+type dm_build_1494 struct {
+	dm_build_1113
+}
+
+func dm_build_1495(dm_build_1496 *dm_build_697) *dm_build_1494 {
+	dm_build_1497 := new(dm_build_1494)
+	dm_build_1497.dm_build_1118(dm_build_1496, Dm_build_986)
+	return dm_build_1497
+}
+
+type dm_build_1498 struct {
+	dm_build_1113
+	dm_build_1499 int32
+}
+
+func dm_build_1500(dm_build_1501 *dm_build_697, dm_build_1502 int32) *dm_build_1498 {
+	dm_build_1503 := new(dm_build_1498)
+	dm_build_1503.dm_build_1118(dm_build_1501, Dm_build_999)
+	dm_build_1503.dm_build_1499 = dm_build_1502
+	return dm_build_1503
+}
+
+func (dm_build_1505 *dm_build_1498) dm_build_1099() error {
+
+	dm_build_1506 := Dm_build_1006
+	dm_build_1506 += dm_build_1505.dm_build_1114.dm_build_700.Dm_build_556(dm_build_1506, g2dbIsoLevel(dm_build_1505.dm_build_1499))
+	return nil
+}
+
+type dm_build_1507 struct {
+	dm_build_1113
+	dm_build_1508 *lob
+	dm_build_1509 byte
+	dm_build_1510 int
+	dm_build_1511 []byte
+	dm_build_1512 int
+	dm_build_1513 int
+}
+
+func dm_build_1514(dm_build_1515 *dm_build_697, dm_build_1516 *lob, dm_build_1517 byte, dm_build_1518 int, dm_build_1519 []byte,
+	dm_build_1520 int, dm_build_1521 int) *dm_build_1507 {
+	dm_build_1522 := new(dm_build_1507)
+	dm_build_1522.dm_build_1118(dm_build_1515, Dm_build_995)
+	dm_build_1522.dm_build_1508 = dm_build_1516
+	dm_build_1522.dm_build_1509 = dm_build_1517
+	dm_build_1522.dm_build_1510 = dm_build_1518
+	dm_build_1522.dm_build_1511 = dm_build_1519
+	dm_build_1522.dm_build_1512 = dm_build_1520
+	dm_build_1522.dm_build_1513 = dm_build_1521
+	return dm_build_1522
+}
+
+func (dm_build_1524 *dm_build_1507) dm_build_1099() error {
+
+	dm_build_1524.dm_build_1114.dm_build_700.Dm_build_404(byte(dm_build_1524.dm_build_1508.lobFlag))
+	dm_build_1524.dm_build_1114.dm_build_700.Dm_build_404(dm_build_1524.dm_build_1509)
+	dm_build_1524.dm_build_1114.dm_build_700.Dm_build_432(uint64(dm_build_1524.dm_build_1508.blobId))
+	dm_build_1524.dm_build_1114.dm_build_700.Dm_build_412(dm_build_1524.dm_build_1508.groupId)
+	dm_build_1524.dm_build_1114.dm_build_700.Dm_build_412(dm_build_1524.dm_build_1508.fileId)
+	dm_build_1524.dm_build_1114.dm_build_700.Dm_build_416(dm_build_1524.dm_build_1508.pageNo)
+	dm_build_1524.dm_build_1114.dm_build_700.Dm_build_412(dm_build_1524.dm_build_1508.curFileId)
+	dm_build_1524.dm_build_1114.dm_build_700.Dm_build_416(dm_build_1524.dm_build_1508.curPageNo)
+	dm_build_1524.dm_build_1114.dm_build_700.Dm_build_416(dm_build_1524.dm_build_1508.totalOffset)
+	dm_build_1524.dm_build_1114.dm_build_700.Dm_build_416(dm_build_1524.dm_build_1508.tabId)
+	dm_build_1524.dm_build_1114.dm_build_700.Dm_build_412(dm_build_1524.dm_build_1508.colId)
+	dm_build_1524.dm_build_1114.dm_build_700.Dm_build_432(uint64(dm_build_1524.dm_build_1508.rowId))
+
+	dm_build_1524.dm_build_1114.dm_build_700.Dm_build_416(int32(dm_build_1524.dm_build_1510))
+	dm_build_1524.dm_build_1114.dm_build_700.Dm_build_416(int32(dm_build_1524.dm_build_1513))
+	dm_build_1524.dm_build_1114.dm_build_700.Dm_build_444(dm_build_1524.dm_build_1511)
+
+	if dm_build_1524.dm_build_1114.dm_build_701.NewLobFlag {
+		dm_build_1524.dm_build_1114.dm_build_700.Dm_build_412(dm_build_1524.dm_build_1508.exGroupId)
+		dm_build_1524.dm_build_1114.dm_build_700.Dm_build_412(dm_build_1524.dm_build_1508.exFileId)
+		dm_build_1524.dm_build_1114.dm_build_700.Dm_build_416(dm_build_1524.dm_build_1508.exPageNo)
+	}
+	return nil
+}
+
+func (dm_build_1526 *dm_build_1507) dm_build_1103() (interface{}, error) {
+
+	var dm_build_1527 = dm_build_1526.dm_build_1114.dm_build_700.Dm_build_490()
+	dm_build_1526.dm_build_1508.blobId = dm_build_1526.dm_build_1114.dm_build_700.Dm_build_493()
+	dm_build_1526.dm_build_1508.fileId = dm_build_1526.dm_build_1114.dm_build_700.Dm_build_487()
+	dm_build_1526.dm_build_1508.pageNo = dm_build_1526.dm_build_1114.dm_build_700.Dm_build_490()
+	dm_build_1526.dm_build_1508.curFileId = dm_build_1526.dm_build_1114.dm_build_700.Dm_build_487()
+	dm_build_1526.dm_build_1508.curPageNo = dm_build_1526.dm_build_1114.dm_build_700.Dm_build_490()
+	dm_build_1526.dm_build_1508.totalOffset = dm_build_1526.dm_build_1114.dm_build_700.Dm_build_490()
+	return dm_build_1527, nil
+}
+
+const (
+	Dm_build_1528 = Dm_build_1006
+
+	Dm_build_1529 = Dm_build_1528 + ULINT_SIZE
+
+	Dm_build_1530 = Dm_build_1529 + ULINT_SIZE
+
+	Dm_build_1531 = Dm_build_1530 + BYTE_SIZE
+
+	Dm_build_1532 = Dm_build_1531 + BYTE_SIZE
+
+	Dm_build_1533 = Dm_build_1532 + BYTE_SIZE
+
+	Dm_build_1534 = Dm_build_1533 + BYTE_SIZE
+
+	Dm_build_1535 = Dm_build_1534 + BYTE_SIZE
+
+	Dm_build_1536 = Dm_build_1535 + BYTE_SIZE
+
+	Dm_build_1537 = Dm_build_1536 + BYTE_SIZE
+
+	Dm_build_1538 = Dm_build_1006
+
+	Dm_build_1539 = Dm_build_1538 + ULINT_SIZE
+
+	Dm_build_1540 = Dm_build_1539 + ULINT_SIZE
+
+	Dm_build_1541 = Dm_build_1540 + ULINT_SIZE
+
+	Dm_build_1542 = Dm_build_1541 + ULINT_SIZE
+
+	Dm_build_1543 = Dm_build_1542 + ULINT_SIZE
+
+	Dm_build_1544 = Dm_build_1543 + BYTE_SIZE
+
+	Dm_build_1545 = Dm_build_1544 + BYTE_SIZE
+
+	Dm_build_1546 = Dm_build_1545 + BYTE_SIZE
+
+	Dm_build_1547 = Dm_build_1546 + BYTE_SIZE
+
+	Dm_build_1548 = Dm_build_1547 + BYTE_SIZE
+
+	Dm_build_1549 = Dm_build_1548 + USINT_SIZE
+
+	Dm_build_1550 = Dm_build_1549 + BYTE_SIZE
+)
+
+type dm_build_1551 struct {
+	dm_build_1113
+	dm_build_1552 *DmConnection
+	dm_build_1553 int
+	Dm_build_1554 int32
+	Dm_build_1555 []byte
+	dm_build_1556 byte
+}
+
+func dm_build_1557(dm_build_1558 *dm_build_697) *dm_build_1551 {
+	dm_build_1559 := new(dm_build_1551)
+	dm_build_1559.dm_build_1118(dm_build_1558, Dm_build_1004)
+	dm_build_1559.dm_build_1552 = dm_build_1558.dm_build_701
+	return dm_build_1559
+}
+
+func dm_build_1560(dm_build_1561 string, dm_build_1562 string) int {
+	dm_build_1563 := strings.Split(dm_build_1561, ".")
+	dm_build_1564 := strings.Split(dm_build_1562, ".")
+
+	for i, serStr := range dm_build_1563 {
+		ser, _ := strconv.ParseInt(serStr, 10, 32)
+		global, _ := strconv.ParseInt(dm_build_1564[i], 10, 32)
+		if ser < global {
+			return -1
+		} else if ser == global {
+			continue
+		} else {
+			return 1
+		}
+	}
+
+	return 0
+}
+
+func (dm_build_1566 *dm_build_1551) dm_build_1099() error {
+
+	dm_build_1566.dm_build_1114.dm_build_700.Dm_build_556(Dm_build_1528, int32(0))
+	dm_build_1566.dm_build_1114.dm_build_700.Dm_build_556(Dm_build_1529, int32(dm_build_1566.dm_build_1552.dmConnector.compress))
+
+	if dm_build_1566.dm_build_1552.dmConnector.loginEncrypt {
+		dm_build_1566.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1531, 2)
+		dm_build_1566.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1530, 1)
+	} else {
+		dm_build_1566.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1531, 0)
+		dm_build_1566.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1530, 0)
+	}
+
+	if dm_build_1566.dm_build_1552.dmConnector.isBdtaRS {
+		dm_build_1566.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1532, Dm_build_1085)
+	} else {
+		dm_build_1566.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1532, Dm_build_1084)
+	}
+
+	dm_build_1566.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1533, byte(dm_build_1566.dm_build_1552.dmConnector.compressID))
+
+	if dm_build_1566.dm_build_1552.dmConnector.loginCertificate != "" {
+		dm_build_1566.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1534, 1)
+	} else {
+		dm_build_1566.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1534, 0)
+	}
+
+	dm_build_1566.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1535, 0)
+	dm_build_1566.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1536, 1)
+	dm_build_1566.dm_build_1114.dm_build_700.Dm_build_576(Dm_build_1537, uint16(dm_build_1566.dm_build_1552.MsgVersion))
+
+	dm_build_1567 := dm_build_1566.dm_build_1552.getServerEncoding()
+	dm_build_1566.dm_build_1114.dm_build_700.Dm_build_460(Dm_build_962, dm_build_1567, dm_build_1566.dm_build_1114.dm_build_701)
+
+	var dm_build_1568 byte
+	if dm_build_1566.dm_build_1552.dmConnector.uKeyName != "" {
+		dm_build_1568 = 1
+	} else {
+		dm_build_1568 = 0
+	}
+
+	dm_build_1566.dm_build_1114.dm_build_700.Dm_build_404(0)
+
+	if dm_build_1568 == 1 {
+
+	}
+
+	if dm_build_1566.dm_build_1552.dmConnector.loginEncrypt {
+		clientPubKey, err := dm_build_1566.dm_build_1114.dm_build_942()
+		if err != nil {
+			return err
+		}
+		dm_build_1566.dm_build_1114.dm_build_700.Dm_build_448(clientPubKey)
+	}
+
+	return nil
+}
+
+func (dm_build_1570 *dm_build_1551) dm_build_1102() error {
+	dm_build_1570.dm_build_1114.dm_build_700.Dm_build_378(0)
+	dm_build_1570.dm_build_1114.dm_build_700.Dm_build_386(Dm_build_1005, false, true)
+	return nil
+}
+
+func (dm_build_1572 *dm_build_1551) dm_build_1103() (interface{}, error) {
+
+	dm_build_1572.dm_build_1552.sslEncrypt = int(dm_build_1572.dm_build_1114.dm_build_700.Dm_build_634(Dm_build_1538))
+	dm_build_1572.dm_build_1552.GlobalServerSeries = int(dm_build_1572.dm_build_1114.dm_build_700.Dm_build_634(Dm_build_1539))
+
+	switch dm_build_1572.dm_build_1114.dm_build_700.Dm_build_634(Dm_build_1540) {
+	case 1:
+		dm_build_1572.dm_build_1552.serverEncoding = ENCODING_UTF8
+	case 2:
+		dm_build_1572.dm_build_1552.serverEncoding = ENCODING_EUCKR
+	default:
+		dm_build_1572.dm_build_1552.serverEncoding = ENCODING_GB18030
+	}
+
+	dm_build_1572.dm_build_1552.dmConnector.compress = int(dm_build_1572.dm_build_1114.dm_build_700.Dm_build_634(Dm_build_1541))
+	dm_build_1573 := dm_build_1572.dm_build_1114.dm_build_700.Dm_build_628(Dm_build_1543)
+	dm_build_1574 := dm_build_1572.dm_build_1114.dm_build_700.Dm_build_628(Dm_build_1544)
+	dm_build_1572.dm_build_1552.dmConnector.isBdtaRS = dm_build_1572.dm_build_1114.dm_build_700.Dm_build_628(Dm_build_1545) > 0
+	dm_build_1572.dm_build_1552.dmConnector.compressID = int8(dm_build_1572.dm_build_1114.dm_build_700.Dm_build_628(Dm_build_1546))
+
+	dm_build_1572.dm_build_1114.dm_build_706 = dm_build_1572.dm_build_1114.dm_build_700.Dm_build_628(Dm_build_1548) == 1
+	dm_build_1572.dm_build_1552.dmConnector.newClientType = dm_build_1572.dm_build_1114.dm_build_700.Dm_build_628(Dm_build_1549) == 1
+	dm_build_1572.dm_build_1552.MsgVersion = int32(dm_build_1572.dm_build_1114.dm_build_700.Dm_build_649(Dm_build_1550))
+
+	dm_build_1575 := dm_build_1572.dm_build_1146()
+	if dm_build_1575 != nil {
+		return nil, dm_build_1575
+	}
+
+	dm_build_1576 := dm_build_1572.dm_build_1114.dm_build_700.Dm_build_532(dm_build_1572.dm_build_1552.getServerEncoding(), dm_build_1572.dm_build_1114.dm_build_701)
+	if dm_build_1560(dm_build_1576, Dm_build_963) < 0 {
+		return nil, ECGO_ERROR_SERVER_VERSION.throw()
+	}
+
+	dm_build_1572.dm_build_1552.ServerVersion = dm_build_1576
+	dm_build_1572.dm_build_1552.Malini2 = dm_build_1560(dm_build_1576, Dm_build_964) > 0
+	dm_build_1572.dm_build_1552.Execute2 = dm_build_1560(dm_build_1576, Dm_build_965) > 0
+	dm_build_1572.dm_build_1552.LobEmptyCompOrcl = dm_build_1560(dm_build_1576, Dm_build_966) > 0
+
+	if dm_build_1572.dm_build_1114.dm_build_701.dmConnector.uKeyName != "" {
+		dm_build_1572.dm_build_1556 = 1
+	} else {
+		dm_build_1572.dm_build_1556 = 0
+	}
+
+	if dm_build_1572.dm_build_1556 == 1 {
+		dm_build_1572.dm_build_1114.dm_build_707 = dm_build_1572.dm_build_1114.dm_build_700.Dm_build_527(16, dm_build_1572.dm_build_1552.getServerEncoding(), dm_build_1572.dm_build_1114.dm_build_701)
+	}
+
+	dm_build_1572.dm_build_1553 = -1
+	dm_build_1577 := false
+	dm_build_1578 := false
+	dm_build_1572.Dm_build_1554 = -1
+	if dm_build_1574 > 0 {
+		dm_build_1572.dm_build_1553 = int(dm_build_1572.dm_build_1114.dm_build_700.Dm_build_490())
+	}
+
+	if dm_build_1573 > 0 {
+
+		if dm_build_1572.dm_build_1553 == -1 {
+			dm_build_1577 = true
+		} else {
+			dm_build_1578 = true
+		}
+
+		dm_build_1572.Dm_build_1555 = dm_build_1572.dm_build_1114.dm_build_700.Dm_build_515()
+	}
+
+	if dm_build_1574 == 2 {
+		dm_build_1572.Dm_build_1554 = dm_build_1572.dm_build_1114.dm_build_700.Dm_build_490()
+	}
+	dm_build_1572.dm_build_1114.dm_build_703 = dm_build_1577
+	dm_build_1572.dm_build_1114.dm_build_704 = dm_build_1578
+
+	return nil, nil
+}
+
+type dm_build_1579 struct {
+	dm_build_1113
+}
+
+func dm_build_1580(dm_build_1581 *dm_build_697, dm_build_1582 *DmStatement) *dm_build_1579 {
+	dm_build_1583 := new(dm_build_1579)
+	dm_build_1583.dm_build_1122(dm_build_1581, Dm_build_980, dm_build_1582)
+	return dm_build_1583
+}
+
+func (dm_build_1585 *dm_build_1579) dm_build_1099() error {
+
+	dm_build_1585.dm_build_1114.dm_build_700.Dm_build_548(Dm_build_1006, 1)
+	return nil
+}
+
+func (dm_build_1587 *dm_build_1579) dm_build_1103() (interface{}, error) {
+
+	dm_build_1587.dm_build_1117.id = dm_build_1587.dm_build_1114.dm_build_700.Dm_build_634(Dm_build_1007)
+
+	dm_build_1587.dm_build_1117.readBaseColName = dm_build_1587.dm_build_1114.dm_build_700.Dm_build_628(Dm_build_1006) == 1
+	return nil, nil
+}
+
+type dm_build_1588 struct {
+	dm_build_1113
+	dm_build_1589 int32
+}
+
+func dm_build_1590(dm_build_1591 *dm_build_697, dm_build_1592 int32) *dm_build_1588 {
+	dm_build_1593 := new(dm_build_1588)
+	dm_build_1593.dm_build_1118(dm_build_1591, Dm_build_981)
+	dm_build_1593.dm_build_1589 = dm_build_1592
+	return dm_build_1593
+}
+
+func (dm_build_1595 *dm_build_1588) dm_build_1100() {
+	dm_build_1595.dm_build_1113.dm_build_1100()
+	dm_build_1595.dm_build_1114.dm_build_700.Dm_build_556(Dm_build_1007, dm_build_1595.dm_build_1589)
+}
+
+type dm_build_1596 struct {
+	dm_build_1113
+	dm_build_1597 []uint32
+}
+
+func dm_build_1598(dm_build_1599 *dm_build_697, dm_build_1600 []uint32) *dm_build_1596 {
+	dm_build_1601 := new(dm_build_1596)
+	dm_build_1601.dm_build_1118(dm_build_1599, Dm_build_1001)
+	dm_build_1601.dm_build_1597 = dm_build_1600
+	return dm_build_1601
+}
+
+func (dm_build_1603 *dm_build_1596) dm_build_1099() error {
+
+	dm_build_1603.dm_build_1114.dm_build_700.Dm_build_576(Dm_build_1006, uint16(len(dm_build_1603.dm_build_1597)))
+
+	for _, tableID := range dm_build_1603.dm_build_1597 {
+		dm_build_1603.dm_build_1114.dm_build_700.Dm_build_428(uint32(tableID))
+	}
+
+	return nil
+}
+
+func (dm_build_1605 *dm_build_1596) dm_build_1103() (interface{}, error) {
+	dm_build_1606 := dm_build_1605.dm_build_1114.dm_build_700.Dm_build_649(Dm_build_1006)
+	if dm_build_1606 <= 0 {
+		return nil, nil
+	}
+
+	dm_build_1607 := make([]int64, dm_build_1606)
+	for i := 0; i < int(dm_build_1606); i++ {
+		dm_build_1607[i] = dm_build_1605.dm_build_1114.dm_build_700.Dm_build_493()
+	}
+
+	return dm_build_1607, nil
+}

+ 205 - 0
zr.go

@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"io"
+)
+
+const (
+	READ_LEN = Dm_build_1089
+)
+
+type iOffRowBinder interface {
+	read(buf *Dm_build_283)
+	isReadOver() bool
+	getObj() interface{}
+}
+
+type offRowBinder struct {
+	obj          interface{}
+	encoding     string
+	readOver     bool
+	buffer       *Dm_build_283
+	position     int32
+	offRow       bool
+	targetLength int64
+}
+
+func newOffRowBinder(obj interface{}, encoding string, targetLength int64) *offRowBinder {
+	return &offRowBinder{
+		obj:          obj,
+		encoding:     encoding,
+		targetLength: targetLength,
+		readOver:     false,
+		buffer:       Dm_build_287(),
+		position:     0,
+	}
+}
+
+type offRowBytesBinder struct {
+	*offRowBinder
+}
+
+func newOffRowBytesBinder(obj []byte, encoding string) *offRowBytesBinder {
+	var binder = &offRowBytesBinder{
+		newOffRowBinder(obj, encoding, int64(IGNORE_TARGET_LENGTH)),
+	}
+	binder.read(binder.buffer)
+	binder.offRow = binder.buffer.Dm_build_288() > Dm_build_1086
+	return binder
+}
+
+func (b *offRowBytesBinder) read(buf *Dm_build_283) {
+	if b.buffer.Dm_build_288() > 0 {
+		buf.Dm_build_320(b.buffer)
+	} else if !b.readOver {
+		var obj = b.obj.([]byte)
+		buf.Dm_build_309(obj, 0, len(obj))
+		b.readOver = true
+	}
+}
+
+func (b *offRowBytesBinder) isReadOver() bool {
+	return b.readOver
+}
+
+func (b *offRowBytesBinder) getObj() interface{} {
+	return b.obj
+}
+
+type offRowBlobBinder struct {
+	*offRowBinder
+}
+
+func newOffRowBlobBinder(blob DmBlob, encoding string) *offRowBlobBinder {
+	var binder = &offRowBlobBinder{
+		newOffRowBinder(blob, encoding, int64(IGNORE_TARGET_LENGTH)),
+	}
+	binder.read(binder.buffer)
+	binder.offRow = binder.buffer.Dm_build_288() > Dm_build_1086
+	return binder
+}
+
+func (b *offRowBlobBinder) read(buf *Dm_build_283) {
+	if b.buffer.Dm_build_288() > 0 {
+		buf.Dm_build_320(b.buffer)
+	} else if !b.readOver {
+		var obj = b.obj.(DmBlob)
+		var totalLen, _ = obj.GetLength()
+		var leaveLen = totalLen - int64(b.position)
+		var readLen = int32(leaveLen)
+		if leaveLen > READ_LEN {
+			readLen = READ_LEN
+		}
+		var bytes, _ = obj.getBytes(int64(b.position)+1, readLen)
+		b.position += readLen
+		if b.position == int32(totalLen) {
+			b.readOver = true
+		}
+		buf.Dm_build_309(bytes, 0, len(bytes))
+	}
+}
+
+func (b *offRowBlobBinder) isReadOver() bool {
+	return b.readOver
+}
+
+func (b *offRowBlobBinder) getObj() interface{} {
+	return b.obj
+}
+
+type offRowClobBinder struct {
+	*offRowBinder
+}
+
+func newOffRowClobBinder(clob DmClob, encoding string) *offRowClobBinder {
+	var binder = &offRowClobBinder{
+		newOffRowBinder(clob, encoding, int64(IGNORE_TARGET_LENGTH)),
+	}
+	binder.read(binder.buffer)
+	binder.offRow = binder.buffer.Dm_build_288() > Dm_build_1086
+	return binder
+}
+
+func (b *offRowClobBinder) read(buf *Dm_build_283) {
+	if b.buffer.Dm_build_288() > 0 {
+		buf.Dm_build_320(b.buffer)
+	} else if !b.readOver {
+		var obj = b.obj.(DmClob)
+		var totalLen, _ = obj.GetLength()
+		var leaveLen = totalLen - int64(b.position)
+		var readLen = int32(leaveLen)
+		if leaveLen > READ_LEN {
+			readLen = READ_LEN
+		}
+		var str, _ = obj.getSubString(int64(b.position)+1, readLen)
+		var bytes = Dm_build_1.Dm_build_217(str, b.encoding, nil)
+		b.position += readLen
+		if b.position == int32(totalLen) {
+			b.readOver = true
+		}
+		buf.Dm_build_309(bytes, 0, len(bytes))
+	}
+}
+
+func (b *offRowClobBinder) isReadOver() bool {
+	return b.readOver
+}
+
+func (b *offRowClobBinder) getObj() interface{} {
+	return b.obj
+}
+
+type offRowReaderBinder struct {
+	*offRowBinder
+}
+
+func newOffRowReaderBinder(reader io.Reader, encoding string) *offRowReaderBinder {
+	var binder = &offRowReaderBinder{
+		newOffRowBinder(reader, encoding, int64(IGNORE_TARGET_LENGTH)),
+	}
+	binder.read(binder.buffer)
+	binder.offRow = binder.buffer.Dm_build_288() > Dm_build_1086
+	return binder
+}
+
+func (b *offRowReaderBinder) read(buf *Dm_build_283) {
+	if b.buffer.Dm_build_288() > 0 {
+		buf.Dm_build_320(b.buffer)
+	} else if !b.readOver {
+		var err error
+		var readLen = READ_LEN
+		var reader = b.obj.(io.Reader)
+		var bytes = make([]byte, readLen)
+		readLen, err = reader.Read(bytes)
+		if err == io.EOF {
+			b.readOver = true
+			return
+		}
+		b.position += int32(readLen)
+		if readLen < len(bytes) || b.targetLength != int64(IGNORE_TARGET_LENGTH) && int64(b.position) == b.targetLength {
+			b.readOver = true
+		}
+		buf.Dm_build_309(bytes[0:readLen], 0, readLen)
+	}
+}
+
+func (b *offRowReaderBinder) readAll() []byte {
+	var byteArray = Dm_build_287()
+	b.read(byteArray)
+	for !b.readOver {
+		b.read(byteArray)
+	}
+	return byteArray.Dm_build_330()
+}
+
+func (b *offRowReaderBinder) isReadOver() bool {
+	return b.readOver
+}
+
+func (b *offRowReaderBinder) getObj() interface{} {
+	return b.obj
+}

+ 882 - 0
zs.go

@@ -0,0 +1,882 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package dm
+
+import (
+	"fmt"
+	"math"
+	"strconv"
+	"strings"
+	"time"
+	"unicode"
+	"unicode/utf8"
+
+	"gitee.com/chunanyong/dm/util"
+)
+
+type oracleDateFormat struct {
+	PM                bool
+	TZNegative        bool
+	pattern           string
+	language          int
+	scale             int32
+	FormatElementList []interface{}
+	YearElement       yearElement
+	MonthElement      monthElement
+	MonElement        monElement
+	MMElement         mmElement
+	DDElement         ddElement
+	HH24Element       hh24Element
+	HH12Element       hh12Element
+	MIElement         miElement
+	SSElement         ssElement
+	FElement          fElement
+	TZHElement        tzhElement
+	TZMElement        tzmElement
+	AMElement         amElement
+}
+
+type element interface {
+	/**
+	 * 从字符串中解析出对应的值,
+	 * @param str 完整的字符串
+	 * @param offset 当前偏移
+	 * @return 解析后的offset
+	 */
+	parse(str string, offset int, dt []int) (int, error)
+
+	/**
+	 * 将时间值value格式化成字符串
+	 */
+	format(dt []int) string
+}
+
+type yearElement struct {
+	OracleDateFormat *oracleDateFormat
+	len              int
+}
+
+func (YearElement yearElement) parse(str string, offset int, dt []int) (int, error) {
+	strLen := 0
+	for i := offset; i < offset+YearElement.len && i < len(str); i++ {
+		if !unicode.IsLetter(rune(str[i])) && !unicode.IsDigit(rune(str[i])) {
+			break
+		}
+		strLen++
+	}
+	str = str[offset : offset+strLen]
+	if YearElement.len < 4 {
+		today := strconv.FormatInt(int64(dt[OFFSET_YEAR]), 10)
+		i, err := strconv.ParseInt(today[:4-YearElement.len]+str, 10, 32)
+		if err != nil {
+			return 0, err
+		}
+		dt[OFFSET_YEAR] = int(i)
+	} else {
+		i, err := strconv.ParseInt(str, 10, 32)
+		if err != nil {
+			return 0, err
+		}
+		dt[OFFSET_YEAR] = int(i)
+	}
+
+	return offset + strLen, nil
+}
+
+func (YearElement yearElement) format(dt []int) string {
+	return YearElement.OracleDateFormat.formatInt(dt[OFFSET_YEAR], YearElement.len)
+}
+
+type monthElement struct {
+	OracleDateFormat *oracleDateFormat
+	upperCase        bool
+	lowerCase        bool
+}
+
+var monthNameList = []string{"", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}
+
+func (MonthElement monthElement) parse(str string, offset int, dt []int) (int, error) {
+
+	if MonthElement.OracleDateFormat.language == LANGUAGE_CN {
+		index := strings.IndexRune(str[offset:], '月')
+		if index == -1 {
+			return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
+		}
+		index += offset
+
+		mon, err := strconv.ParseInt(str[offset:index], 10, 32)
+		if err != nil {
+			return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
+		}
+
+		if mon > 12 || mon < 1 {
+			return -1, ECGO_INVALID_DATETIME_VALUE.throw()
+		}
+		dt[OFFSET_MONTH] = int(mon)
+		return index + utf8.RuneLen('月'), nil
+	} else {
+		str = str[offset:]
+		mon := 0
+		for i := 1; i < len(monthNameList); i++ {
+			if util.StringUtil.StartWithIgnoreCase(str, monthNameList[i]) {
+				mon = i
+				break
+			}
+		}
+		if mon == 0 {
+			return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
+		}
+		dt[OFFSET_MONTH] = mon
+		return offset + len(monthNameList[mon]), nil
+	}
+}
+
+func (MonthElement monthElement) format(dt []int) string {
+	value := dt[OFFSET_MONTH]
+
+	if MonthElement.OracleDateFormat.language == LANGUAGE_CN {
+		return strconv.FormatInt(int64(value), 10) + "月"
+	}
+
+	if MonthElement.upperCase {
+		return strings.ToUpper(monthNameList[value])
+	} else if MonthElement.lowerCase {
+		return strings.ToLower(monthNameList[value])
+	} else {
+		return monthNameList[value]
+	}
+
+}
+
+type monElement struct {
+	OracleDateFormat *oracleDateFormat
+	upperCase        bool
+	lowerCase        bool
+}
+
+var monNameList []string = []string{"", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}
+
+func (MonElement monElement) parse(str string, offset int, dt []int) (int, error) {
+
+	if MonElement.OracleDateFormat.language == LANGUAGE_CN {
+		index := strings.IndexRune(str[offset:], '月') + offset
+		if index == -1+offset {
+			return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
+		}
+
+		mon, err := strconv.ParseInt(str[offset:index], 10, 32)
+		if err != nil {
+			return -1, err
+		}
+
+		if mon > 12 || mon < 1 {
+			return -1, ECGO_INVALID_DATETIME_VALUE.throw()
+		}
+		dt[OFFSET_MONTH] = int(mon)
+		return index + utf8.RuneLen('月'), nil
+	} else {
+		str = str[offset : offset+3]
+		mon := 0
+		for i := 1; i < len(monNameList); i++ {
+			if util.StringUtil.EqualsIgnoreCase(str, monNameList[i]) {
+				mon = i
+				break
+			}
+		}
+		if mon == 0 {
+			return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
+		}
+		dt[OFFSET_MONTH] = mon
+		return offset + 3, nil
+	}
+
+}
+
+func (MonElement monElement) format(dt []int) string {
+	value := dt[OFFSET_MONTH]
+	language := int(0)
+	if language == LANGUAGE_CN {
+		return strconv.FormatInt(int64(value), 10) + "月"
+	}
+
+	if MonElement.upperCase {
+		return strings.ToUpper(monNameList[value])
+	} else if MonElement.lowerCase {
+		return strings.ToLower(monNameList[value])
+	} else {
+		return monNameList[value]
+	}
+}
+
+type mmElement struct {
+	OracleDateFormat *oracleDateFormat
+}
+
+func (MMElement mmElement) parse(str string, offset int, dt []int) (int, error) {
+	strLen := 0
+	for i := offset; i < offset+2 && i < len(str); i++ {
+		if !unicode.IsLetter(rune(str[i])) && !unicode.IsDigit(rune(str[i])) {
+			break
+		}
+		strLen++
+	}
+	str = str[offset : offset+strLen]
+	month, err := strconv.ParseInt(str, 10, 32)
+	if err != nil {
+		return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
+	}
+
+	if month > 12 || month < 1 {
+		return -1, ECGO_INVALID_DATETIME_VALUE.throw()
+	}
+	dt[OFFSET_MONTH] = int(month)
+	return offset + strLen, nil
+}
+
+func (MMElement mmElement) format(dt []int) string {
+	return MMElement.OracleDateFormat.formatInt(dt[OFFSET_MONTH], 2)
+}
+
+type ddElement struct {
+	OracleDateFormat *oracleDateFormat
+}
+
+func (DDElement ddElement) parse(str string, offset int, dt []int) (int, error) {
+	strLen := 0
+	for i := offset; i < offset+2 && i < len(str); i++ {
+		if !unicode.IsLetter(rune(str[i])) && !unicode.IsDigit(rune(str[i])) {
+			break
+		}
+		strLen++
+	}
+	str = str[offset : offset+strLen]
+	day, err := strconv.ParseInt(str, 10, 32)
+	if err != nil {
+		return -1, err
+	}
+
+	if day > 31 || day < 1 {
+		return -1, ECGO_INVALID_DATETIME_VALUE.throw()
+	}
+	dt[OFFSET_DAY] = int(day)
+	return offset + strLen, nil
+}
+
+func (DDElement ddElement) format(dt []int) string {
+	return DDElement.OracleDateFormat.formatInt(dt[OFFSET_DAY], 2)
+}
+
+type hh24Element struct {
+	OracleDateFormat *oracleDateFormat
+}
+
+func (HH24Element hh24Element) parse(str string, offset int, dt []int) (int, error) {
+	strLen := 0
+	for i := offset; i < offset+2 && i < len(str); i++ {
+		if !unicode.IsLetter(rune(str[i])) && !unicode.IsDigit(rune(str[i])) {
+			break
+		}
+		strLen++
+	}
+	str = str[offset : offset+strLen]
+	hour, err := strconv.ParseInt(str, 10, 32)
+	if err != nil {
+		return -1, err
+	}
+
+	if hour > 23 || hour < 0 {
+		return -1, ECGO_INVALID_DATETIME_VALUE.throw()
+	}
+	dt[OFFSET_HOUR] = int(hour) // 0-23
+	return offset + strLen, nil
+}
+
+func (HH24Element hh24Element) format(dt []int) string {
+	return HH24Element.OracleDateFormat.formatInt(dt[OFFSET_HOUR], 2) // 0-23
+}
+
+type hh12Element struct {
+	OracleDateFormat *oracleDateFormat
+}
+
+func (HH12Element hh12Element) parse(str string, offset int, dt []int) (int, error) {
+	strLen := 0
+	for i := offset; i < offset+2 && i < len(str); i++ {
+		if !unicode.IsLetter(rune(str[i])) && !unicode.IsDigit(rune(str[i])) {
+			break
+		}
+		strLen++
+	}
+	str = str[offset : offset+strLen]
+	hour, err := strconv.ParseInt(str, 10, 32)
+	if err != nil {
+		return -1, err
+	}
+
+	if hour > 12 || hour < 1 {
+		return -1, ECGO_INVALID_DATETIME_VALUE.throw()
+	}
+	dt[OFFSET_HOUR] = int(hour)
+	return offset + strLen, nil
+}
+
+func (HH12Element hh12Element) format(dt []int) string {
+	var ret string
+	value := dt[OFFSET_HOUR]
+	if value > 12 || value == 0 {
+		ret = HH12Element.OracleDateFormat.formatInt(int(math.Abs(float64(value-12))), 2) // 1-12
+	} else {
+		ret = HH12Element.OracleDateFormat.formatInt(value, 2)
+	}
+	return ret
+}
+
+type miElement struct {
+	OracleDateFormat *oracleDateFormat
+}
+
+func (MIElement miElement) parse(str string, offset int, dt []int) (int, error) {
+	strLen := 0
+	for i := offset; i < offset+2 && i < len(str); i++ {
+		if !unicode.IsLetter(rune(str[i])) && !unicode.IsDigit(rune(str[i])) {
+			break
+		}
+		strLen++
+	}
+	str = str[offset : offset+strLen]
+	minute, err := strconv.ParseInt(str, 10, 32)
+	if err != nil {
+		return -1, err
+	}
+
+	if minute > 59 || minute < 0 {
+		return -1, ECGO_INVALID_DATETIME_VALUE.throw()
+	}
+	dt[OFFSET_MINUTE] = int(minute) // 0-59
+	return offset + strLen, nil
+}
+
+func (MIElement miElement) format(dt []int) string {
+	return MIElement.OracleDateFormat.formatInt(dt[OFFSET_MINUTE], 2) // 0-59
+}
+
+type ssElement struct {
+	OracleDateFormat *oracleDateFormat
+}
+
+func (SSElement ssElement) parse(str string, offset int, dt []int) (int, error) {
+	strLen := 0
+	for i := offset; i < offset+2 && i < len(str); i++ {
+		if !unicode.IsLetter(rune(str[i])) && !unicode.IsDigit(rune(str[i])) {
+			break
+		}
+		strLen++
+	}
+	str = str[offset : offset+strLen]
+	second, err := strconv.ParseInt(str, 10, 32)
+	if err != nil {
+		return -1, err
+	}
+
+	if second > 59 || second < 0 {
+		return -1, ECGO_INVALID_DATETIME_VALUE.throw()
+	}
+	dt[OFFSET_SECOND] = int(second) // 0-59
+	return offset + strLen, nil
+}
+
+func (SSElement ssElement) format(dt []int) string {
+	return SSElement.OracleDateFormat.formatInt(dt[OFFSET_SECOND], 2) // 0-59
+}
+
+type fElement struct {
+	OracleDateFormat *oracleDateFormat
+	len              int
+}
+
+func (FElement fElement) parse(str string, offset int, dt []int) (int, error) {
+	strLen := 0
+	maxLen := 0
+	if FElement.len > 0 {
+		maxLen = FElement.len
+	} else {
+		maxLen = NANOSECOND_DIGITS
+	}
+	for i := offset; i < offset+maxLen && i < len(str); i++ {
+		if !unicode.IsLetter(rune(str[i])) && !unicode.IsDigit(rune(str[i])) {
+			break
+		}
+		strLen++
+	}
+	str = str[offset : offset+strLen]
+	ms, err := strconv.ParseInt(str, 10, 32)
+	if err != nil {
+		return -1, err
+	}
+
+	if strLen < NANOSECOND_DIGITS {
+		ms *= int64(math.Pow10(NANOSECOND_DIGITS - strLen))
+	} else {
+		ms /= int64(math.Pow10(strLen - NANOSECOND_DIGITS))
+	}
+
+	dt[OFFSET_NANOSECOND] = int(ms)
+	return offset + strLen, nil
+}
+
+func (FElement fElement) format(dt []int) string {
+	msgLen := 0
+	if FElement.len > 0 {
+		msgLen = FElement.len
+	} else {
+		msgLen = int(FElement.OracleDateFormat.scale)
+	}
+	return FElement.OracleDateFormat.formatMilliSecond(dt[OFFSET_NANOSECOND], msgLen)
+}
+
+type tzhElement struct {
+	OracleDateFormat *oracleDateFormat
+}
+
+func (TZHElement tzhElement) parse(str string, offset int, dt []int) (int, error) {
+	if str[offset] == '+' {
+		offset += 1
+	} else if str[offset] == '-' {
+		offset += 1
+		TZHElement.OracleDateFormat.TZNegative = true
+	}
+
+	strLen := 0
+	for i := offset; i < offset+2 && i < len(str); i++ {
+		if !unicode.IsLetter(rune(str[i])) && !unicode.IsDigit(rune(str[i])) {
+			break
+		}
+		strLen++
+	}
+	str = str[offset : offset+strLen]
+
+	tzh, err := strconv.ParseInt(str, 10, 32)
+	if err != nil {
+		return -1, err
+	}
+
+	if tzh > 23 || tzh < 0 {
+		return -1, ECGO_INVALID_DATETIME_VALUE.throw()
+	}
+
+	tzh *= 60
+	if dt[OFFSET_TIMEZONE] == int(INVALID_VALUE) {
+		dt[OFFSET_TIMEZONE] = int(tzh)
+	} else {
+		dt[OFFSET_TIMEZONE] += int(tzh)
+	}
+
+	return offset + strLen, nil
+}
+
+func (TZHElement tzhElement) format(dt []int) string {
+	var value int
+	if dt[OFFSET_TIMEZONE] != int(INVALID_VALUE) {
+		value = int(math.Abs(float64(dt[OFFSET_TIMEZONE]))) / 60
+	} else {
+		value = 0
+	}
+
+	return TZHElement.OracleDateFormat.formatInt(value, 2)
+}
+
+type tzmElement struct {
+	OracleDateFormat *oracleDateFormat
+}
+
+func (TZMElement tzmElement) parse(str string, offset int, dt []int) (int, error) {
+	if str[offset] == '+' {
+		offset += 1
+	} else if str[offset] == '-' {
+		offset += 1
+		TZMElement.OracleDateFormat.TZNegative = true
+	}
+
+	strLen := 0
+	for i := offset; i < offset+2 && i < len(str); i++ {
+		if !unicode.IsLetter(rune(str[i])) && !unicode.IsDigit(rune(str[i])) {
+			break
+		}
+		strLen++
+	}
+	str = str[offset : offset+strLen]
+
+	tzm, err := strconv.ParseInt(str, 10, 32)
+	if err != nil {
+		return -1, err
+	}
+	if tzm > 59 || tzm < 0 {
+		return -1, ECGO_INVALID_DATETIME_VALUE.throw()
+	}
+
+	if dt[OFFSET_TIMEZONE] == INVALID_VALUE {
+		dt[OFFSET_TIMEZONE] = int(tzm)
+	} else {
+		dt[OFFSET_TIMEZONE] += int(tzm)
+	}
+	return offset + strLen, nil
+}
+
+func (TZMElement tzmElement) format(dt []int) string {
+	var value int
+	if dt[OFFSET_TIMEZONE] != int(INVALID_VALUE) {
+		value = int(math.Abs(float64(dt[OFFSET_TIMEZONE]))) % 60
+	} else {
+		value = 0
+	}
+
+	return TZMElement.OracleDateFormat.formatInt(value, 2)
+}
+
+type amElement struct {
+	OracleDateFormat *oracleDateFormat
+}
+
+func (AMElement amElement) parse(str string, offset int, dt []int) (int, error) {
+	runeStr := ([]rune(str))[offset : offset+2]
+
+	if AMElement.OracleDateFormat.language == LANGUAGE_CN {
+		if util.StringUtil.EqualsIgnoreCase("下午", string(runeStr)) {
+			AMElement.OracleDateFormat.PM = true
+			return offset + utf8.RuneLen('下') + utf8.RuneLen('午'), nil
+		} else {
+			AMElement.OracleDateFormat.PM = false
+			return offset + utf8.RuneLen('上') + utf8.RuneLen('午'), nil
+		}
+
+	} else if util.StringUtil.EqualsIgnoreCase("PM", string(runeStr)) {
+		AMElement.OracleDateFormat.PM = true
+	} else {
+		AMElement.OracleDateFormat.PM = false
+	}
+
+	return offset + 2, nil
+}
+
+func (AMElement amElement) format(dt []int) string {
+	hour := dt[OFFSET_HOUR]
+	language := int(0)
+	if language == LANGUAGE_CN {
+		if hour > 12 {
+			return "下午"
+		} else {
+			return "上午"
+		}
+	}
+
+	if hour > 12 {
+		return "PM"
+	} else {
+		return "AM"
+	}
+}
+
+/**
+ * 将int值格式化成指定长度,长度不足前面补0,长度超过的取末尾指定长度
+ */
+func (OracleDateFormat *oracleDateFormat) formatInt(value int, len int) string {
+	pow := int(math.Pow10(len))
+	if value >= pow {
+		value %= pow
+	}
+	value += pow
+	return strconv.FormatInt(int64(value), 10)[1:]
+}
+
+/**
+ * 格式化毫秒值
+ * @param ms
+ * @param len <= 6
+ */
+func (OracleDateFormat *oracleDateFormat) formatMilliSecond(ms int, len int) string {
+	var ret string
+	if ms < 10 {
+		ret = "00000" + strconv.FormatInt(int64(ms), 10)
+	} else if ms < 100 {
+		ret = "0000" + strconv.FormatInt(int64(ms), 10)
+	} else if ms < 1000 {
+		ret = "000" + strconv.FormatInt(int64(ms), 10)
+	} else if ms < 10000 {
+		ret = "00" + strconv.FormatInt(int64(ms), 10)
+	} else if ms < 100000 {
+		ret = "0" + strconv.FormatInt(int64(ms), 10)
+	} else {
+		ret = strconv.FormatInt(int64(ms), 10)
+	}
+
+	if len < 6 {
+		ret = ret[:len]
+	}
+	return ret
+}
+
+func getFormat() *oracleDateFormat {
+	format := new(oracleDateFormat)
+	format.PM = false
+	format.TZNegative = false
+	format.YearElement = yearElement{format, 4}
+	format.MonthElement = monthElement{format, false, false}
+	format.MonElement = monElement{format, false, false}
+	format.MMElement = mmElement{format}
+	format.DDElement = ddElement{format}
+	format.HH24Element = hh24Element{format}
+	format.HH12Element = hh12Element{format}
+	format.MIElement = miElement{format}
+	format.SSElement = ssElement{format}
+	format.FElement = fElement{format, -1}
+	format.TZHElement = tzhElement{format}
+	format.TZMElement = tzmElement{format}
+	format.AMElement = amElement{format}
+
+	return format
+}
+
+func (OracleDateFormat *oracleDateFormat) parse(str string) (ret []int, err error) {
+	defer func() {
+		if p := recover(); p != nil {
+			err = ECGO_INVALID_DATETIME_FORMAT.throw()
+		}
+	}()
+	OracleDateFormat.TZNegative = false
+	OracleDateFormat.PM = false
+	dt := make([]int, DT_LEN)
+	// oracle默认年月日为 当前时间
+	today := time.Now()
+	dt[OFFSET_YEAR] = today.Year()
+	dt[OFFSET_MONTH] = int(today.Month())
+	dt[OFFSET_DAY] = today.Day()
+	dt[OFFSET_TIMEZONE] = INVALID_VALUE
+	offset := 0
+	str = strings.TrimSpace(str)
+	for _, obj := range OracleDateFormat.FormatElementList {
+		// 跳过空格
+		for str[offset] == ' ' && fmt.Sprintf("%+v", obj) != " " {
+			offset++
+		}
+		if e, ok := obj.(element); ok {
+			offset, err = e.parse(str, offset, dt)
+			if err != nil {
+				return nil, err
+			}
+		} else {
+			offset += len(obj.(string))
+		}
+	}
+	if offset < len(str) {
+		//[6103]:文字与格式字符串不匹配.
+		return nil, ECGO_INVALID_DATETIME_VALUE.throw()
+	}
+
+	// 12小时制时间转换
+	if OracleDateFormat.PM {
+		dt[OFFSET_HOUR] = (dt[OFFSET_HOUR] + 12) % 24
+	}
+
+	// 时区符号保留
+	if OracleDateFormat.TZNegative {
+		dt[OFFSET_TIMEZONE] = -dt[OFFSET_TIMEZONE]
+	}
+
+	// check day
+	if dt[OFFSET_DAY] > getDaysOfMonth(dt[OFFSET_YEAR], dt[OFFSET_MONTH]) || dt[OFFSET_DAY] < 1 {
+		return nil, ECGO_INVALID_DATETIME_VALUE.throw()
+	}
+	// check timezone 兼容oracle
+	if dt[OFFSET_TIMEZONE] != INVALID_VALUE && (dt[OFFSET_TIMEZONE] > 14*60 || dt[OFFSET_TIMEZONE] <= -13*60) {
+		return nil, ECGO_INVALID_DATETIME_VALUE.throw()
+	}
+	return dt, nil
+}
+
+func parse(str string, pattern string, language int) ([]int, error) {
+	f := getFormat()
+	f.setPattern(pattern)
+	f.language = language
+	return f.parse(str)
+}
+
+func (OracleDateFormat *oracleDateFormat) setPattern(pattern string) {
+	if pattern != OracleDateFormat.pattern {
+		OracleDateFormat.pattern = pattern
+		OracleDateFormat.FormatElementList = OracleDateFormat.FormatElementList[:0]
+		OracleDateFormat.analysePattern(pattern)
+	}
+}
+
+func format(dt []int, pattern string, scale int32, language int) string {
+	f := getFormat()
+	f.setPattern(pattern)
+	f.language = language
+	f.scale = scale
+	ret := f.format(dt)
+	return ret
+}
+
+func (OracleDateFormat *oracleDateFormat) format(dt []int) string {
+	sf := strings.Builder{}
+	tzStart := false
+	for _, obj := range OracleDateFormat.FormatElementList {
+		_, ok1 := obj.(tzhElement)
+		_, ok2 := obj.(tzmElement)
+		if !tzStart && (ok1 || ok2) {
+			tzStart = true
+			if dt[OFFSET_TIMEZONE] < 0 {
+				sf.WriteString("-")
+			} else {
+				sf.WriteString("+")
+			}
+		}
+
+		if e, ok := obj.(element); ok {
+			sf.WriteString(e.format(dt))
+		} else {
+			sf.WriteString(obj.(string))
+		}
+	}
+	return sf.String()
+}
+
+/**
+ * 解析格式串
+ */
+func (OracleDateFormat *oracleDateFormat) analysePattern(pattern string) ([]interface{}, error) {
+
+	// 按分隔符split
+	pattern = strings.TrimSpace(pattern)
+	l := len(pattern)
+	var splitPatterns []string
+	starti := 0
+	var curChar rune
+	for i := 0; i < l; i++ {
+		curChar = rune(pattern[i])
+		if !unicode.IsDigit(curChar) && !unicode.IsLetter(curChar) {
+			if i > starti {
+				splitPatterns = append(splitPatterns, pattern[starti:i])
+			}
+
+			splitPatterns = append(splitPatterns, string(curChar))
+			starti = i + 1
+		} else if i == l-1 {
+			splitPatterns = append(splitPatterns, pattern[starti:i+1])
+		}
+	}
+
+	// 每个串按照从完整串,然后依次去掉一个末尾字符 来进行尝试规约
+	for _, subPattern := range splitPatterns {
+		if len(subPattern) != 1 || unicode.IsDigit(rune(subPattern[0])) || unicode.IsLetter(rune(subPattern[0])) {
+			fmtWord := subPattern
+			for subPattern != "" {
+				i := len(subPattern)
+				for ; i > 0; i-- {
+					fmtWord = subPattern[0:i]
+					element, err := OracleDateFormat.getFormatElement(fmtWord)
+					if err != nil {
+						return nil, err
+					}
+					if element != nil {
+						// 忽略时区前面的+-号
+						if element == OracleDateFormat.TZHElement || element == OracleDateFormat.TZMElement {
+							var lastFormatElement string = OracleDateFormat.FormatElementList[len(OracleDateFormat.FormatElementList)-1].(string)
+							if util.StringUtil.Equals("+", lastFormatElement) || util.StringUtil.Equals("-", lastFormatElement) {
+								OracleDateFormat.FormatElementList = OracleDateFormat.FormatElementList[:len(OracleDateFormat.FormatElementList)-2]
+							}
+						}
+						OracleDateFormat.FormatElementList = append(OracleDateFormat.FormatElementList, element)
+						if i == len(subPattern) {
+							subPattern = ""
+						} else {
+							subPattern = subPattern[i:len(subPattern)]
+						}
+						break
+					}
+				}
+
+				if i == 0 {
+					// 非标识符串
+					OracleDateFormat.FormatElementList = append(OracleDateFormat.FormatElementList, subPattern)
+					break
+				}
+			}
+
+		} else {
+			OracleDateFormat.FormatElementList = append(OracleDateFormat.FormatElementList, subPattern)
+		}
+	}
+	return OracleDateFormat.FormatElementList, nil
+}
+
+func (OracleDateFormat *oracleDateFormat) getFormatElement(word string) (element, error) {
+	if util.StringUtil.EqualsIgnoreCase("HH", word) || util.StringUtil.EqualsIgnoreCase("HH12", word) {
+		return OracleDateFormat.HH12Element, nil
+	} else if util.StringUtil.EqualsIgnoreCase("HH24", word) {
+		return OracleDateFormat.HH24Element, nil
+	} else if util.StringUtil.EqualsIgnoreCase("MI", word) {
+		return OracleDateFormat.MIElement, nil
+	} else if util.StringUtil.EqualsIgnoreCase("SS", word) {
+		return OracleDateFormat.SSElement, nil
+	} else if util.StringUtil.EqualsIgnoreCase("AM", word) || util.StringUtil.EqualsIgnoreCase("A.M.", word) || util.StringUtil.EqualsIgnoreCase("PM", word) || util.StringUtil.EqualsIgnoreCase("P.M.", word) {
+		return OracleDateFormat.AMElement, nil
+	} else if util.StringUtil.Equals("MONTH", word) {
+		OracleDateFormat.MonthElement.upperCase = true
+		OracleDateFormat.MonthElement.lowerCase = false
+		return OracleDateFormat.MonthElement, nil
+	} else if util.StringUtil.Equals("month", word) {
+		OracleDateFormat.MonthElement.upperCase = false
+		OracleDateFormat.MonthElement.lowerCase = true
+		return OracleDateFormat.MonthElement, nil
+	} else if util.StringUtil.EqualsIgnoreCase("Month", word) {
+		OracleDateFormat.MonthElement.upperCase = false
+		OracleDateFormat.MonthElement.lowerCase = false
+		return OracleDateFormat.MonthElement, nil
+	} else if util.StringUtil.Equals("MON", word) {
+		OracleDateFormat.MonElement.upperCase = true
+		OracleDateFormat.MonElement.lowerCase = false
+		return OracleDateFormat.MonElement, nil
+	} else if util.StringUtil.Equals("mon", word) {
+		OracleDateFormat.MonElement.upperCase = false
+		OracleDateFormat.MonElement.lowerCase = true
+		return OracleDateFormat.MonElement, nil
+	} else if util.StringUtil.EqualsIgnoreCase("Mon", word) {
+		OracleDateFormat.MonElement.upperCase = false
+		OracleDateFormat.MonElement.lowerCase = false
+		return OracleDateFormat.MonElement, nil
+	} else if util.StringUtil.EqualsIgnoreCase("MM", word) {
+		return OracleDateFormat.MMElement, nil
+	} else if util.StringUtil.EqualsIgnoreCase("DD", word) {
+		return OracleDateFormat.DDElement, nil
+	} else if util.StringUtil.EqualsIgnoreCase("TZH", word) {
+		return OracleDateFormat.TZHElement, nil
+	} else if util.StringUtil.EqualsIgnoreCase("TZM", word) {
+		return OracleDateFormat.TZMElement, nil
+	} else if strings.Index(word, "Y") == 0 || strings.Index(word, "y") == 0 {
+		OracleDateFormat.YearElement.len = len(word)
+		return OracleDateFormat.YearElement, nil
+	} else if strings.Index(word, "F") == 0 || strings.Index(word, "f") == 0 {
+
+		word = strings.ToUpper(word)
+		numIndex := strings.LastIndex(word, "F") + 1
+		var count int64
+		var err error
+		if numIndex < len(word) {
+			count, err = strconv.ParseInt(word[numIndex:len(word)], 10, 32)
+			if err != nil {
+				return nil, err
+			}
+		} else {
+			count = -1
+		}
+
+		OracleDateFormat.FElement.len = int(count)
+		return OracleDateFormat.FElement, nil
+	}
+
+	return nil, nil
+}

+ 124 - 0
zv.go

@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package dm
+
+import (
+	"strconv"
+	"strings"
+)
+
+type Properties struct {
+	innerProps map[string]string
+}
+
+func NewProperties() *Properties {
+	p := Properties{
+		innerProps: make(map[string]string, 50),
+	}
+	return &p
+}
+
+func (g *Properties) SetProperties(p *Properties) {
+	if p == nil {
+		return
+	}
+	for k, v := range p.innerProps {
+		g.Set(strings.ToLower(k), v)
+	}
+}
+
+func (g *Properties) Len() int {
+	return len(g.innerProps)
+}
+
+func (g *Properties) IsNil() bool {
+	return g == nil || g.innerProps == nil
+}
+
+func (g *Properties) GetString(key, def string) string {
+	v, ok := g.innerProps[strings.ToLower(key)]
+
+	if !ok || v == "" {
+		return def
+	}
+	return v
+}
+
+func (g *Properties) GetInt(key string, def int, min int, max int) int {
+	value, ok := g.innerProps[strings.ToLower(key)]
+	if !ok || value == "" {
+		return def
+	}
+
+	i, err := strconv.Atoi(value)
+	if err != nil {
+		return def
+	}
+
+	if i > max || i < min {
+		return def
+	}
+	return i
+}
+
+func (g *Properties) GetBool(key string, def bool) bool {
+	value, ok := g.innerProps[strings.ToLower(key)]
+	if !ok || value == "" {
+		return def
+	}
+	b, err := strconv.ParseBool(value)
+	if err != nil {
+		return def
+	}
+	return b
+}
+
+func (g *Properties) GetTrimString(key string, def string) string {
+	value, ok := g.innerProps[strings.ToLower(key)]
+	if !ok || value == "" {
+		return def
+	} else {
+		return strings.TrimSpace(value)
+	}
+}
+
+func (g *Properties) GetStringArray(key string, def []string) []string {
+	value, ok := g.innerProps[strings.ToLower(key)]
+	if ok || value != "" {
+		array := strings.Split(value, ",")
+		if len(array) > 0 {
+			return array
+		}
+	}
+	return def
+}
+
+//func (g *Properties) GetBool(key string) bool {
+//	i, _ := strconv.ParseBool(g.innerProps[key])
+//	return i
+//}
+
+func (g *Properties) Set(key, value string) {
+	g.innerProps[strings.ToLower(key)] = value
+}
+
+func (g *Properties) SetIfNotExist(key, value string) {
+	if _, ok := g.innerProps[strings.ToLower(key)]; !ok {
+		g.Set(key, value)
+	}
+}
+
+// 如果p有g没有的键值对,添加进g中
+func (g *Properties) SetDiffProperties(p *Properties) {
+	if p == nil {
+		return
+	}
+	for k, v := range p.innerProps {
+		if _, ok := g.innerProps[strings.ToLower(k)]; !ok {
+			g.innerProps[strings.ToLower(k)] = v
+		}
+	}
+}

+ 220 - 0
zw.go

@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package dm
+
+import (
+	"math/rand"
+	"strconv"
+	"time"
+
+	"gitee.com/chunanyong/dm/util"
+)
+
+var rwMap = make(map[string]*rwCounter)
+
+type rwCounter struct {
+	ntrx_primary int64
+
+	ntrx_total int64
+
+	primaryPercent float64
+
+	standbyPercent float64
+
+	standbyNTrxMap map[string]int64
+
+	standbyIdMap map[string]int32
+
+	standbyCount int32
+
+	flag []int32
+
+	increments []int32
+}
+
+func newRWCounter(primaryPercent int32, standbyCount int32) *rwCounter {
+	rwc := new(rwCounter)
+	rwc.standbyNTrxMap = make(map[string]int64)
+	rwc.standbyIdMap = make(map[string]int32)
+	rwc.reset(primaryPercent, standbyCount)
+	return rwc
+}
+
+func (rwc *rwCounter) reset(primaryPercent int32, standbyCount int32) {
+	rwc.ntrx_primary = 0
+	rwc.ntrx_total = 0
+	rwc.standbyCount = standbyCount
+	rwc.increments = make([]int32, standbyCount+1)
+	rwc.flag = make([]int32, standbyCount+1)
+	var gcd = util.GCD(primaryPercent*standbyCount, 100-primaryPercent)
+	rwc.increments[0] = primaryPercent * standbyCount / gcd
+	for i, tmp := 1, (100-primaryPercent)/gcd; i < len(rwc.increments); i++ {
+		rwc.increments[i] = tmp
+	}
+	copy(rwc.flag, rwc.increments)
+
+	if standbyCount > 0 {
+		rwc.primaryPercent = float64(primaryPercent) / 100.0
+		rwc.standbyPercent = float64(100-primaryPercent) / 100.0 / float64(standbyCount)
+	} else {
+		rwc.primaryPercent = 1
+		rwc.standbyPercent = 0
+	}
+}
+
+// 连接创建成功后调用,需要服务器返回standbyCount
+func getRwCounterInstance(conn *DmConnection, standbyCount int32) *rwCounter {
+	key := conn.dmConnector.host + "_" + strconv.Itoa(int(conn.dmConnector.port)) + "_" + strconv.Itoa(int(conn.dmConnector.rwPercent))
+
+	rwc, ok := rwMap[key]
+	if !ok {
+		rwc = newRWCounter(conn.dmConnector.rwPercent, standbyCount)
+		rwMap[key] = rwc
+	} else if rwc.standbyCount != standbyCount {
+		rwc.reset(conn.dmConnector.rwPercent, standbyCount)
+	}
+	return rwc
+}
+
+/**
+* @return 主机;
+ */
+func (rwc *rwCounter) countPrimary() RWSiteEnum {
+	rwc.adjustNtrx()
+	rwc.increasePrimaryNtrx()
+	return PRIMARY
+}
+
+/**
+* @param dest 主机; 备机; any;
+* @return 主机; 备机
+ */
+func (rwc *rwCounter) count(dest RWSiteEnum, standby *DmConnection) RWSiteEnum {
+	rwc.adjustNtrx()
+	switch dest {
+	case ANYSITE:
+		{
+			if rwc.primaryPercent == 1 || (rwc.flag[0] > rwc.getStandbyFlag(standby) && rwc.flag[0] > util.Sum(rwc.flag[1:])) {
+				rwc.increasePrimaryNtrx()
+				dest = PRIMARY
+			} else {
+				rwc.increaseStandbyNtrx(standby)
+				dest = STANDBY
+			}
+		}
+	case STANDBY:
+		{
+			rwc.increaseStandbyNtrx(standby)
+		}
+	case PRIMARY:
+		{
+			rwc.increasePrimaryNtrx()
+		}
+	}
+	return dest
+}
+
+/**
+* 防止ntrx超出有效范围,等比调整
+ */
+func (rwc *rwCounter) adjustNtrx() {
+	if rwc.ntrx_total >= INT64_MAX {
+		var min int64
+		var i = 0
+		for _, num := range rwc.standbyNTrxMap {
+			if i == 0 || num < min {
+				min = num
+			}
+			i++
+		}
+		if rwc.ntrx_primary < min {
+			min = rwc.ntrx_primary
+		}
+		rwc.ntrx_primary /= min
+		rwc.ntrx_total /= min
+		for k, v := range rwc.standbyNTrxMap {
+			rwc.standbyNTrxMap[k] = v / min
+		}
+	}
+
+	if rwc.flag[0] <= 0 && util.Sum(rwc.flag[1:]) <= 0 {
+		// 如果主库事务数以及所有备库事务数的总和 都 <= 0, 重置事务计数,给每个库的事务计数加上初始计数值
+		for i := 0; i < len(rwc.flag); i++ {
+			rwc.flag[i] += rwc.increments[i]
+		}
+	}
+}
+
+func (rwc *rwCounter) increasePrimaryNtrx() {
+	rwc.ntrx_primary++
+	rwc.flag[0]--
+	rwc.ntrx_total++
+}
+
+//func (rwc *rwCounter) getStandbyNtrx(standby *DmConnection) int64 {
+//	key := standby.dmConnector.host + ":" + strconv.Itoa(int(standby.dmConnector.port))
+//	ret, ok := rwc.standbyNTrxMap[key]
+//	if !ok {
+//		ret = 0
+//	}
+//
+//	return ret
+//}
+
+func (rwc *rwCounter) getStandbyId(standby *DmConnection) int32 {
+	key := standby.dmConnector.host + ":" + strconv.Itoa(int(standby.dmConnector.port))
+	sid, ok := rwc.standbyIdMap[key]
+	if !ok {
+		sid = int32(len(rwc.standbyIdMap) + 1) // 下标0是primary
+		if sid > rwc.standbyCount {
+			// 不在有效备库中
+			return -1
+		}
+		rwc.standbyIdMap[key] = sid
+	}
+	return sid
+}
+
+func (rwc *rwCounter) getStandbyFlag(standby *DmConnection) int32 {
+	sid := rwc.getStandbyId(standby)
+	if sid > 0 && sid < int32(len(rwc.flag)) {
+		// 保证备库有效
+		return rwc.flag[sid]
+	}
+	return 0
+}
+
+func (rwc *rwCounter) increaseStandbyNtrx(standby *DmConnection) {
+	key := standby.dmConnector.host + ":" + strconv.Itoa(int(standby.dmConnector.port))
+	ret, ok := rwc.standbyNTrxMap[key]
+	if ok {
+		ret += 1
+	} else {
+		ret = 1
+	}
+	rwc.standbyNTrxMap[key] = ret
+	sid, ok := rwc.standbyIdMap[key]
+	if !ok {
+		sid = int32(len(rwc.standbyIdMap) + 1) // 下标0是primary
+		rwc.standbyIdMap[key] = sid
+	}
+	rwc.flag[sid]--
+	rwc.ntrx_total++
+}
+
+func (rwc *rwCounter) random(rowCount int32) int32 {
+	rand.Seed(time.Now().UnixNano())
+	if rowCount > rwc.standbyCount {
+		return rand.Int31n(rwc.standbyCount)
+	} else {
+		return rand.Int31n(rowCount)
+	}
+}
+
+func (rwc *rwCounter) String() string {
+	return "PERCENT(P/S) : " + strconv.FormatFloat(rwc.primaryPercent, 'f', -1, 64) + "/" + strconv.FormatFloat(rwc.standbyPercent, 'f', -1, 64) + "\nNTRX_PRIMARY : " +
+		strconv.FormatInt(rwc.ntrx_primary, 10) + "\nNTRX_TOTAL : " + strconv.FormatInt(rwc.ntrx_total, 10) + "\nNTRX_STANDBY : "
+}

+ 421 - 0
zx.go

@@ -0,0 +1,421 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"context"
+	"database/sql"
+	"database/sql/driver"
+	"errors"
+	"io"
+	"regexp"
+	"strings"
+	"time"
+
+	"gitee.com/chunanyong/dm/util"
+)
+
+const (
+	SQL_SELECT_STANDBY = "select distinct mailIni.inst_name, mailIni.INST_IP, mailIni.INST_PORT, archIni.arch_status " +
+		"from  v$arch_status archIni " +
+		"left join (select * from V$DM_MAL_INI) mailIni on archIni.arch_dest = mailIni.inst_name " +
+		"left join V$MAL_LINK_STATUS on CTL_LINK_STATUS  = 'CONNECTED' AND DATA_LINK_STATUS = 'CONNECTED' " +
+		"where archIni.arch_type in ('TIMELY', 'REALTIME') AND  archIni.arch_status = 'VALID'"
+
+	SQL_SELECT_STANDBY2 = "select distinct " +
+		"mailIni.mal_inst_name, mailIni.mal_INST_HOST, mailIni.mal_INST_PORT, archIni.arch_status " +
+		"from v$arch_status archIni " + "left join (select * from V$DM_MAL_INI) mailIni " +
+		"on archIni.arch_dest = mailIni.mal_inst_name " + "left join V$MAL_LINK_STATUS " +
+		"on CTL_LINK_STATUS  = 'CONNECTED' AND DATA_LINK_STATUS = 'CONNECTED' " +
+		"where archIni.arch_type in ('TIMELY', 'REALTIME') AND  archIni.arch_status = 'VALID'"
+)
+
+type rwUtil struct {
+}
+
+var RWUtil = rwUtil{}
+
+func (RWUtil rwUtil) connect(c *DmConnector, ctx context.Context) (*DmConnection, error) {
+	c.loginMode = LOGIN_MODE_PRIMARY_ONLY
+	connection, err := c.connect(ctx)
+	if err != nil {
+		return nil, err
+	}
+
+	connection.rwInfo.rwCounter = getRwCounterInstance(connection, connection.StandbyCount)
+	err = RWUtil.connectStandby(connection)
+
+	return connection, err
+}
+
+func (RWUtil rwUtil) reconnect(connection *DmConnection) error {
+	if connection.rwInfo == nil {
+		return nil
+	}
+
+	RWUtil.removeStandby(connection)
+
+	err := connection.reconnect()
+	if err != nil {
+		return err
+	}
+	connection.rwInfo.cleanup()
+	connection.rwInfo.rwCounter = getRwCounterInstance(connection, connection.StandbyCount)
+
+	err = RWUtil.connectStandby(connection)
+
+	return err
+}
+
+func (RWUtil rwUtil) recoverStandby(connection *DmConnection) error {
+	if connection.closed.IsSet() || RWUtil.isStandbyAlive(connection) {
+		return nil
+	}
+
+	ts := time.Now().UnixNano() / 1000000
+
+	freq := int64(connection.dmConnector.rwStandbyRecoverTime)
+	if freq <= 0 || ts-connection.rwInfo.tryRecoverTs < freq {
+		return nil
+	}
+
+	err := RWUtil.connectStandby(connection)
+	connection.rwInfo.tryRecoverTs = ts
+
+	return err
+}
+
+func (RWUtil rwUtil) connectStandby(connection *DmConnection) error {
+	var err error
+	db, err := RWUtil.chooseValidStandby(connection)
+	if err != nil {
+		return err
+	}
+	if db == nil {
+		return nil
+	}
+
+	standbyConnectorValue := *connection.dmConnector
+	standbyConnector := &standbyConnectorValue
+	standbyConnector.host = db.host
+	standbyConnector.port = db.port
+	standbyConnector.rwStandby = true
+	standbyConnector.group = nil
+	standbyConnector.loginMode = LOGIN_MODE_STANDBY_ONLY
+	standbyConnector.switchTimes = 0
+	connection.rwInfo.connStandby, err = standbyConnector.connectSingle(context.Background())
+	if err != nil {
+		return err
+	}
+
+	if connection.rwInfo.connStandby.SvrMode != SERVER_MODE_STANDBY || connection.rwInfo.connStandby.SvrStat != SERVER_STATUS_OPEN {
+		RWUtil.removeStandby(connection)
+	}
+	return nil
+}
+
+func (RWUtil rwUtil) chooseValidStandby(connection *DmConnection) (*ep, error) {
+	stmt, rs, err := connection.driverQuery(SQL_SELECT_STANDBY2)
+	if err != nil {
+		stmt, rs, err = connection.driverQuery(SQL_SELECT_STANDBY)
+	}
+	defer func() {
+		if rs != nil {
+			rs.close()
+		}
+		if stmt != nil {
+			stmt.close()
+		}
+	}()
+	if err == nil {
+		count := int32(rs.CurrentRows.getRowCount())
+		if count > 0 {
+			connection.rwInfo.rwCounter = getRwCounterInstance(connection, count)
+			i := int32(0)
+			rowIndex := connection.rwInfo.rwCounter.random(count)
+			dest := make([]driver.Value, 3)
+			for err := rs.next(dest); err != io.EOF; err = rs.next(dest) {
+				if i == rowIndex {
+					ep := newEP(dest[1].(string), dest[2].(int32))
+					return ep, nil
+				}
+				i++
+			}
+		}
+	}
+	if err != nil {
+		return nil, errors.New("choose valid standby error!" + err.Error())
+	}
+	return nil, nil
+}
+
+func (RWUtil rwUtil) afterExceptionOnStandby(connection *DmConnection, e error) {
+	if e.(*DmError).ErrCode == ECGO_COMMUNITION_ERROR.ErrCode {
+		RWUtil.removeStandby(connection)
+	}
+}
+
+func (RWUtil rwUtil) removeStandby(connection *DmConnection) {
+	if connection.rwInfo.connStandby != nil {
+		connection.rwInfo.connStandby.close()
+		connection.rwInfo.connStandby = nil
+	}
+}
+
+func (RWUtil rwUtil) isCreateStandbyStmt(stmt *DmStatement) bool {
+	return stmt != nil && stmt.rwInfo.readOnly && RWUtil.isStandbyAlive(stmt.dmConn)
+}
+
+func (RWUtil rwUtil) executeByConn(conn *DmConnection, query string, execute1 func() (interface{}, error), execute2 func(otherConn *DmConnection) (interface{}, error)) (interface{}, error) {
+
+	if err := RWUtil.recoverStandby(conn); err != nil {
+		return nil, err
+	}
+	RWUtil.distributeSqlByConn(conn, query)
+
+	turnToPrimary := false
+
+	ret, err := execute1()
+	if err != nil {
+		if conn.rwInfo.connCurrent == conn.rwInfo.connStandby {
+
+			RWUtil.afterExceptionOnStandby(conn, err)
+			turnToPrimary = true
+		} else {
+
+			return nil, err
+		}
+	}
+
+	curConn := conn.rwInfo.connCurrent
+	var otherConn *DmConnection
+	if curConn != conn {
+		otherConn = conn
+	} else {
+		otherConn = conn.rwInfo.connStandby
+	}
+
+	switch curConn.lastExecInfo.retSqlType {
+	case Dm_build_1063, Dm_build_1064, Dm_build_1068, Dm_build_1075, Dm_build_1074, Dm_build_1066:
+		{
+
+			if otherConn != nil {
+				execute2(otherConn)
+			}
+		}
+	case Dm_build_1073:
+		{
+
+			sqlhead := regexp.MustCompile("[ (]").Split(strings.TrimSpace(query), 2)[0]
+			if util.StringUtil.EqualsIgnoreCase(sqlhead, "SP_SET_PARA_VALUE") || util.StringUtil.EqualsIgnoreCase(sqlhead, "SP_SET_SESSION_READONLY") {
+				if otherConn != nil {
+					execute2(otherConn)
+				}
+			}
+		}
+	case Dm_build_1072:
+		{
+
+			if conn.dmConnector.rwHA && curConn == conn.rwInfo.connStandby &&
+				(curConn.lastExecInfo.rsDatas == nil || len(curConn.lastExecInfo.rsDatas) == 0) {
+				turnToPrimary = true
+			}
+		}
+	}
+
+	if turnToPrimary {
+		conn.rwInfo.toPrimary()
+		conn.rwInfo.connCurrent = conn
+
+		return execute2(conn)
+	}
+	return ret, nil
+}
+
+func (RWUtil rwUtil) executeByStmt(stmt *DmStatement, execute1 func() (interface{}, error), execute2 func(otherStmt *DmStatement) (interface{}, error)) (interface{}, error) {
+	orgStmt := stmt.rwInfo.stmtCurrent
+	query := stmt.nativeSql
+
+	if err := RWUtil.recoverStandby(stmt.dmConn); err != nil {
+		return nil, err
+	}
+	RWUtil.distributeSqlByStmt(stmt)
+	if orgStmt != stmt.rwInfo.stmtCurrent {
+		RWUtil.copyStatement(orgStmt, stmt.rwInfo.stmtCurrent)
+		stmt.rwInfo.stmtCurrent.nativeSql = orgStmt.nativeSql
+	}
+
+	turnToPrimary := false
+
+	ret, err := execute1()
+	if err != nil {
+
+		if stmt.rwInfo.stmtCurrent == stmt.rwInfo.stmtStandby {
+			RWUtil.afterExceptionOnStandby(stmt.dmConn, err)
+			turnToPrimary = true
+		} else {
+			return nil, err
+		}
+	}
+
+	curStmt := stmt.rwInfo.stmtCurrent
+	var otherStmt *DmStatement
+	if curStmt != stmt {
+		otherStmt = stmt
+	} else {
+		otherStmt = stmt.rwInfo.stmtStandby
+	}
+
+	switch curStmt.execInfo.retSqlType {
+	case Dm_build_1063, Dm_build_1064, Dm_build_1068, Dm_build_1075, Dm_build_1074, Dm_build_1066:
+		{
+
+			if otherStmt != nil {
+				RWUtil.copyStatement(curStmt, otherStmt)
+				execute2(otherStmt)
+			}
+		}
+	case Dm_build_1073:
+		{
+
+			var tmpsql string
+			if query != "" {
+				tmpsql = strings.TrimSpace(query)
+			} else if stmt.nativeSql != "" {
+				tmpsql = strings.TrimSpace(stmt.nativeSql)
+			} else {
+				tmpsql = ""
+			}
+			sqlhead := regexp.MustCompile("[ (]").Split(tmpsql, 2)[0]
+			if util.StringUtil.EqualsIgnoreCase(sqlhead, "SP_SET_PARA_VALUE") || util.StringUtil.EqualsIgnoreCase(sqlhead, "SP_SET_SESSION_READONLY") {
+				if otherStmt != nil {
+					RWUtil.copyStatement(curStmt, otherStmt)
+					execute2(otherStmt)
+				}
+			}
+		}
+	case Dm_build_1072:
+		{
+
+			if stmt.dmConn.dmConnector.rwHA && curStmt == stmt.rwInfo.stmtStandby &&
+				(curStmt.execInfo.rsDatas == nil || len(curStmt.execInfo.rsDatas) == 0) {
+				turnToPrimary = true
+			}
+		}
+	}
+
+	if turnToPrimary {
+		stmt.dmConn.rwInfo.toPrimary()
+		stmt.rwInfo.stmtCurrent = stmt
+
+		RWUtil.copyStatement(stmt.rwInfo.stmtStandby, stmt)
+
+		return execute2(stmt)
+	}
+	return ret, nil
+}
+
+func (RWUtil rwUtil) checkReadonlyByConn(conn *DmConnection, sql string) bool {
+	readonly := true
+
+	if sql != "" && !conn.dmConnector.rwIgnoreSql {
+		tmpsql := strings.TrimSpace(sql)
+		sqlhead := strings.SplitN(tmpsql, " ", 2)[0]
+		if util.StringUtil.EqualsIgnoreCase(sqlhead, "INSERT") ||
+			util.StringUtil.EqualsIgnoreCase(sqlhead, "UPDATE") ||
+			util.StringUtil.EqualsIgnoreCase(sqlhead, "DELETE") ||
+			util.StringUtil.EqualsIgnoreCase(sqlhead, "CREATE") ||
+			util.StringUtil.EqualsIgnoreCase(sqlhead, "TRUNCATE") ||
+			util.StringUtil.EqualsIgnoreCase(sqlhead, "DROP") ||
+			util.StringUtil.EqualsIgnoreCase(sqlhead, "ALTER") {
+			readonly = false
+		} else {
+			readonly = true
+		}
+	}
+	return readonly
+}
+
+func (RWUtil rwUtil) checkReadonlyByStmt(stmt *DmStatement) bool {
+	return RWUtil.checkReadonlyByConn(stmt.dmConn, stmt.nativeSql)
+}
+
+func (RWUtil rwUtil) distributeSqlByConn(conn *DmConnection, query string) RWSiteEnum {
+	var dest RWSiteEnum
+	if !RWUtil.isStandbyAlive(conn) {
+
+		dest = conn.rwInfo.toPrimary()
+	} else if !RWUtil.checkReadonlyByConn(conn, query) {
+
+		dest = conn.rwInfo.toPrimary()
+	} else if (conn.rwInfo.distribute == PRIMARY && !conn.trxFinish) ||
+		(conn.rwInfo.distribute == STANDBY && !conn.rwInfo.connStandby.trxFinish) {
+
+		dest = conn.rwInfo.distribute
+	} else if conn.IsoLevel != int32(sql.LevelSerializable) {
+
+		dest = conn.rwInfo.toAny()
+	} else {
+		dest = conn.rwInfo.toPrimary()
+	}
+
+	if dest == PRIMARY {
+		conn.rwInfo.connCurrent = conn
+	} else {
+		conn.rwInfo.connCurrent = conn.rwInfo.connStandby
+	}
+	return dest
+}
+
+func (RWUtil rwUtil) distributeSqlByStmt(stmt *DmStatement) RWSiteEnum {
+	var dest RWSiteEnum
+	if !RWUtil.isStandbyAlive(stmt.dmConn) {
+
+		dest = stmt.dmConn.rwInfo.toPrimary()
+	} else if !RWUtil.checkReadonlyByStmt(stmt) {
+
+		dest = stmt.dmConn.rwInfo.toPrimary()
+	} else if (stmt.dmConn.rwInfo.distribute == PRIMARY && !stmt.dmConn.trxFinish) ||
+		(stmt.dmConn.rwInfo.distribute == STANDBY && !stmt.dmConn.rwInfo.connStandby.trxFinish) {
+
+		dest = stmt.dmConn.rwInfo.distribute
+	} else if stmt.dmConn.IsoLevel != int32(sql.LevelSerializable) {
+
+		dest = stmt.dmConn.rwInfo.toAny()
+	} else {
+		dest = stmt.dmConn.rwInfo.toPrimary()
+	}
+
+	if dest == STANDBY && !RWUtil.isStandbyStatementValid(stmt) {
+
+		var err error
+		stmt.rwInfo.stmtStandby, err = stmt.dmConn.rwInfo.connStandby.prepare(stmt.nativeSql)
+		if err != nil {
+			dest = stmt.dmConn.rwInfo.toPrimary()
+		}
+	}
+
+	if dest == PRIMARY {
+		stmt.rwInfo.stmtCurrent = stmt
+	} else {
+		stmt.rwInfo.stmtCurrent = stmt.rwInfo.stmtStandby
+	}
+	return dest
+}
+
+func (RWUtil rwUtil) isStandbyAlive(connection *DmConnection) bool {
+	return connection.rwInfo.connStandby != nil && !connection.rwInfo.connStandby.closed.IsSet()
+}
+
+func (RWUtil rwUtil) isStandbyStatementValid(statement *DmStatement) bool {
+	return statement.rwInfo.stmtStandby != nil && !statement.rwInfo.stmtStandby.closed
+}
+
+func (RWUtil rwUtil) copyStatement(srcStmt *DmStatement, destStmt *DmStatement) {
+	destStmt.nativeSql = srcStmt.nativeSql
+	destStmt.serverParams = srcStmt.serverParams
+	destStmt.bindParams = srcStmt.bindParams
+	destStmt.paramCount = srcStmt.paramCount
+}

+ 108 - 0
zzj.go

@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package dm
+
+import (
+	"database/sql"
+	"database/sql/driver"
+)
+
+var SQLName sqlName
+
+type sqlName struct {
+	m_name string // 描述对象自身名称,
+
+	// 若为内置类型,则表示数据库端定义的名称,与dType相对应
+	m_pkgName string // 所在包的名称,适用于包中类型的定义
+
+	m_schName string // 描述对象所在模式名
+
+	m_fulName string // 描述对象完全限定名, 记录用户发送的名称信息;
+
+	// 以及接受服务器响应后,拼成的名称信息
+
+	m_schId int // 保存模式id,模式名无法传出,利用模式id查找
+
+	m_packId int // 保存包的id,包名无法传出,用于查找包名
+
+	m_conn *DmConnection
+}
+
+func (SqlName *sqlName) init() {
+	SqlName.m_name = ""
+	SqlName.m_pkgName = ""
+	SqlName.m_schName = ""
+	SqlName.m_fulName = ""
+	SqlName.m_schId = -1
+	SqlName.m_packId = -1
+	SqlName.m_conn = nil
+}
+
+func newSqlNameByFulName(fulName string) *sqlName {
+	o := new(sqlName)
+	o.init()
+	o.m_fulName = fulName
+	return o
+}
+
+func newSqlNameByConn(conn *DmConnection) *sqlName {
+	o := new(sqlName)
+	o.init()
+	o.m_conn = conn
+	return o
+}
+
+func (SqlName *sqlName) getFulName() (string, error) {
+	// 说明非内嵌式数据类型名称描述信息传入或已经获取过描述信息
+	if len(SqlName.m_fulName) > 0 {
+		return SqlName.m_fulName, nil
+	}
+
+	// 内嵌式数据类型无名称描述信息返回,直接返回null
+	if SqlName.m_name == "" {
+		// DBError.throwUnsupportedSQLException();
+		return "", nil
+	}
+
+	// 其他数据名描述信息
+	if SqlName.m_packId != 0 || SqlName.m_schId != 0 {
+		query := "SELECT NAME INTO ? FROM SYS.SYSOBJECTS WHERE ID=?"
+
+		params := make([]driver.Value, 2)
+		var v string
+		params[0] = sql.Out{Dest: &v}
+		if SqlName.m_packId != 0 {
+			params[1] = SqlName.m_packId
+		} else {
+			params[1] = SqlName.m_schId
+		}
+
+		rs, err := SqlName.m_conn.query(query, params)
+		if err != nil {
+			return "", err
+		}
+		rs.close()
+
+		// 说明是包中定义的对象
+		if SqlName.m_packId != 0 {
+			// pkg全名
+			SqlName.m_pkgName = v
+			SqlName.m_fulName = SqlName.m_pkgName + "." + SqlName.m_name
+		} else {
+			// 非包中定义的对象
+			// schema 名称
+			SqlName.m_schName = v
+			SqlName.m_fulName = SqlName.m_schName + "." + SqlName.m_name
+		}
+	}
+	// 将有效值返回
+	if len(SqlName.m_fulName) > 0 {
+		return SqlName.m_fulName, nil
+	} else {
+		return SqlName.m_name, nil
+	}
+
+}

+ 320 - 0
zzk.go

@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"bytes"
+	"strconv"
+	"strings"
+
+	"gitee.com/chunanyong/dm/parser"
+
+	"gitee.com/chunanyong/dm/util"
+)
+
+func (dc *DmConnection) lex(sql string) ([]*parser.LVal, error) {
+	if dc.lexer == nil {
+		dc.lexer = parser.NewLexer(strings.NewReader(sql), false)
+	} else {
+		dc.lexer.Reset(strings.NewReader(sql))
+	}
+
+	lexer := dc.lexer
+	var lval *parser.LVal
+	var err error
+	lvalList := make([]*parser.LVal, 0, 64)
+	lval, err = lexer.Yylex()
+	if err != nil {
+		return nil, err
+	}
+
+	for lval != nil {
+		lvalList = append(lvalList, lval)
+		lval.Position = len(lvalList)
+		lval, err = lexer.Yylex()
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return lvalList, nil
+}
+
+func lexSkipWhitespace(sql string, n int) ([]*parser.LVal, error) {
+	lexer := parser.NewLexer(strings.NewReader(sql), false)
+
+	var lval *parser.LVal
+	var err error
+	lvalList := make([]*parser.LVal, 0, 64)
+	lval, err = lexer.Yylex()
+	if err != nil {
+		return nil, err
+	}
+
+	for lval != nil && n > 0 {
+		lval.Position = len(lvalList)
+		if lval.Tp == parser.WHITESPACE_OR_COMMENT {
+			continue
+		}
+
+		lvalList = append(lvalList, lval)
+		n--
+		lval, err = lexer.Yylex()
+		if err != nil {
+			return nil, err
+		}
+
+	}
+
+	return lvalList, nil
+}
+
+func (dc *DmConnection) escape(sql string, keywords []string) (string, error) {
+
+	if (keywords == nil || len(keywords) == 0) && strings.Index(sql, "{") == -1 {
+		return sql, nil
+	}
+	var keywordMap map[string]interface{}
+	if keywords != nil && len(keywords) > 0 {
+		keywordMap = make(map[string]interface{}, len(keywords))
+		for _, keyword := range keywords {
+			keywordMap[strings.ToUpper(keyword)] = nil
+		}
+	}
+	nsql := bytes.NewBufferString("")
+	stack := make([]bool, 0, 64)
+	lvalList, err := dc.lex(sql)
+	if err != nil {
+		return "", err
+	}
+
+	for i := 0; i < len(lvalList); i++ {
+		lval0 := lvalList[i]
+		if lval0.Tp == parser.NORMAL {
+			if lval0.Value == "{" {
+				lval1 := next(lvalList, i+1)
+				if lval1 == nil || lval1.Tp != parser.NORMAL {
+					stack = append(stack, false)
+					nsql.WriteString(lval0.Value)
+				} else if util.StringUtil.EqualsIgnoreCase(lval1.Value, "escape") || util.StringUtil.EqualsIgnoreCase(lval1.Value, "call") {
+					stack = append(stack, true)
+				} else if util.StringUtil.EqualsIgnoreCase(lval1.Value, "oj") {
+					stack = append(stack, true)
+					lval1.Value = ""
+					lval1.Tp = parser.WHITESPACE_OR_COMMENT
+				} else if util.StringUtil.EqualsIgnoreCase(lval1.Value, "d") {
+					stack = append(stack, true)
+					lval1.Value = "date"
+				} else if util.StringUtil.EqualsIgnoreCase(lval1.Value, "t") {
+					stack = append(stack, true)
+					lval1.Value = "time"
+				} else if util.StringUtil.EqualsIgnoreCase(lval1.Value, "ts") {
+					stack = append(stack, true)
+					lval1.Value = "datetime"
+				} else if util.StringUtil.EqualsIgnoreCase(lval1.Value, "fn") {
+					stack = append(stack, true)
+					lval1.Value = ""
+					lval1.Tp = parser.WHITESPACE_OR_COMMENT
+					lval2 := next(lvalList, lval1.Position+1)
+					if lval2 != nil && lval2.Tp == parser.NORMAL && util.StringUtil.EqualsIgnoreCase(lval2.Value, "database") {
+						lval2.Value = "cur_database"
+					}
+				} else if util.StringUtil.Equals(lval1.Value, "?") {
+					lval2 := next(lvalList, lval1.Position+1)
+					if lval2 != nil && lval2.Tp == parser.NORMAL && util.StringUtil.EqualsIgnoreCase(lval2.Value, "=") {
+						lval3 := next(lvalList, lval2.Position+1)
+						if lval3 != nil && lval3.Tp == parser.NORMAL && util.StringUtil.EqualsIgnoreCase(lval3.Value, "call") {
+							stack = append(stack, true)
+							lval3.Value = ""
+							lval3.Tp = parser.WHITESPACE_OR_COMMENT
+						} else {
+							stack = append(stack, false)
+							nsql.WriteString(lval0.Value)
+						}
+					} else {
+						stack = append(stack, false)
+						nsql.WriteString(lval0.Value)
+					}
+				} else {
+					stack = append(stack, false)
+					nsql.WriteString(lval0.Value)
+				}
+			} else if util.StringUtil.Equals(lval0.Value, "}") {
+				if len(stack) != 0 && stack[len(stack)-1] {
+
+				} else {
+					nsql.WriteString(lval0.Value)
+				}
+				stack = stack[:len(stack)-1]
+			} else {
+				if keywordMap != nil {
+					_, ok := keywordMap[strings.ToUpper(lval0.Value)]
+					if ok {
+						nsql.WriteString("\"" + util.StringUtil.ProcessDoubleQuoteOfName(strings.ToUpper(lval0.Value)) + "\"")
+					} else {
+						nsql.WriteString(lval0.Value)
+					}
+				} else {
+					nsql.WriteString(lval0.Value)
+				}
+			}
+		} else if lval0.Tp == parser.STRING {
+			nsql.WriteString("'" + util.StringUtil.ProcessSingleQuoteOfName(lval0.Value) + "'")
+		} else {
+			nsql.WriteString(lval0.Value)
+		}
+	}
+
+	return nsql.String(), nil
+}
+
+func next(lvalList []*parser.LVal, start int) *parser.LVal {
+	var lval *parser.LVal
+
+	size := len(lvalList)
+	for i := start; i < size; i++ {
+		lval = lvalList[i]
+		if lval.Tp != parser.WHITESPACE_OR_COMMENT {
+			break
+		}
+	}
+	return lval
+}
+
+func (dc *DmConnection) execOpt(sql string, optParamList []OptParameter, serverEncoding string) (string, []OptParameter, error) {
+	nsql := bytes.NewBufferString("")
+
+	lvalList, err := dc.lex(sql)
+	if err != nil {
+		return "", optParamList, err
+	}
+
+	if nil == lvalList || len(lvalList) == 0 {
+		return sql, optParamList, nil
+	}
+
+	firstWord := lvalList[0].Value
+	if !(util.StringUtil.EqualsIgnoreCase(firstWord, "INSERT") || util.StringUtil.EqualsIgnoreCase(firstWord, "SELECT") ||
+		util.StringUtil.EqualsIgnoreCase(firstWord, "UPDATE") || util.StringUtil.EqualsIgnoreCase(firstWord, "DELETE")) {
+		return sql, optParamList, nil
+	}
+
+	breakIndex := 0
+	for i := 0; i < len(lvalList); i++ {
+		lval := lvalList[i]
+		switch lval.Tp {
+		case parser.NULL:
+			{
+				nsql.WriteString("?")
+				optParamList = append(optParamList, newOptParameter(nil, NULL, NULL_PREC))
+			}
+		case parser.INT:
+			{
+				nsql.WriteString("?")
+				value, err := strconv.Atoi(lval.Value)
+				if err != nil {
+					return "", optParamList, err
+				}
+
+				if value <= int(INT32_MAX) && value >= int(INT32_MIN) {
+					optParamList = append(optParamList, newOptParameter(G2DB.toInt32(int32(value)), INT, INT_PREC))
+
+				} else {
+					optParamList = append(optParamList, newOptParameter(G2DB.toInt64(int64(value)), BIGINT, BIGINT_PREC))
+				}
+			}
+		case parser.DOUBLE:
+			{
+				nsql.WriteString("?")
+				f, err := strconv.ParseFloat(lval.Value, 64)
+				if err != nil {
+					return "", optParamList, err
+				}
+
+				optParamList = append(optParamList, newOptParameter(G2DB.toFloat64(f), DOUBLE, DOUBLE_PREC))
+			}
+		case parser.DECIMAL:
+			{
+				nsql.WriteString("?")
+				bytes, err := G2DB.toDecimal(lval.Value, 0, 0)
+				if err != nil {
+					return "", optParamList, err
+				}
+				optParamList = append(optParamList, newOptParameter(bytes, DECIMAL, 0))
+			}
+		case parser.STRING:
+			{
+
+				if len(lval.Value) > int(INT16_MAX) {
+
+					nsql.WriteString("'" + util.StringUtil.ProcessSingleQuoteOfName(lval.Value) + "'")
+				} else {
+					nsql.WriteString("?")
+					optParamList = append(optParamList, newOptParameter(Dm_build_1.Dm_build_217(lval.Value, serverEncoding, dc), VARCHAR, VARCHAR_PREC))
+				}
+			}
+		case parser.HEX_INT:
+
+			nsql.WriteString(lval.Value)
+		default:
+
+			nsql.WriteString(lval.Value)
+		}
+
+		if breakIndex > 0 {
+			break
+		}
+	}
+
+	if breakIndex > 0 {
+		for i := breakIndex + 1; i < len(lvalList); i++ {
+			nsql.WriteString(lvalList[i].Value)
+		}
+	}
+
+	return nsql.String(), optParamList, nil
+}
+
+func (dc *DmConnection) hasConst(sql string) (bool, error) {
+	lvalList, err := dc.lex(sql)
+	if err != nil {
+		return false, err
+	}
+
+	if nil == lvalList || len(lvalList) == 0 {
+		return false, nil
+	}
+
+	for i := 0; i < len(lvalList); i++ {
+		switch lvalList[i].Tp {
+		case parser.NULL, parser.INT, parser.DOUBLE, parser.DECIMAL, parser.STRING, parser.HEX_INT:
+			return true, nil
+		}
+	}
+	return false, nil
+}
+
+type OptParameter struct {
+	bytes  []byte
+	ioType byte
+	tp     int
+	prec   int
+	scale  int
+}
+
+func newOptParameter(bytes []byte, tp int, prec int) OptParameter {
+	o := new(OptParameter)
+	o.bytes = bytes
+	o.tp = tp
+	o.prec = prec
+	return *o
+}
+
+func (parameter *OptParameter) String() string {
+	if parameter.bytes == nil {
+		return ""
+	}
+	return string(parameter.bytes)
+}

+ 44 - 0
zzl.go

@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package dm
+
+type StructDescriptor struct {
+	m_typeDesc *TypeDescriptor
+}
+
+func newStructDescriptor(fulName string, conn *DmConnection) (*StructDescriptor, error) {
+	sd := new(StructDescriptor)
+	if fulName == "" {
+		return nil, ECGO_INVALID_COMPLEX_TYPE_NAME.throw()
+	}
+
+	sd.m_typeDesc = newTypeDescriptorWithFulName(fulName, conn)
+
+	err := sd.m_typeDesc.parseDescByName()
+	if err != nil {
+		return nil, err
+	}
+
+	return sd, nil
+}
+
+func newStructDescriptorByTypeDescriptor(desc *TypeDescriptor) *StructDescriptor {
+	sd := new(StructDescriptor)
+	sd.m_typeDesc = desc
+	return sd
+}
+
+func (sd *StructDescriptor) getSize() int {
+	return sd.m_typeDesc.m_size
+}
+
+func (sd *StructDescriptor) getObjId() int {
+	return sd.m_typeDesc.m_objId
+}
+
+func (sd *StructDescriptor) getItemsDesc() []TypeDescriptor {
+	return sd.m_typeDesc.m_fieldsObj
+}

+ 441 - 0
zzm.go

@@ -0,0 +1,441 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+
+package dm
+
+import (
+	"bufio"
+	"io"
+	"os"
+	"runtime"
+	"strconv"
+	"strings"
+
+	"gitee.com/chunanyong/dm/util"
+)
+
+var LogDirDef, _ = os.Getwd()
+
+var StatDirDef, _ = os.Getwd()
+
+const (
+	DEFAULT_PORT int32 = 5236
+
+	//log level
+	LOG_OFF int = 0
+
+	LOG_ERROR int = 1
+
+	LOG_WARN int = 2
+
+	LOG_SQL int = 3
+
+	LOG_INFO int = 4
+
+	LOG_DEBUG int = 5
+
+	LOG_ALL int = 9
+
+	//stat
+	STAT_SQL_REMOVE_LATEST int = 0
+
+	STAT_SQL_REMOVE_OLDEST int = 1
+
+	// 编码字符集
+	ENCODING_UTF8 string = "UTF-8"
+
+	ENCODING_EUCKR string = "EUC-KR"
+
+	ENCODING_GB18030 string = "GB18030"
+
+	DbAliveCheckFreqDef = 0
+
+	LocaleDef = 0
+
+	// log
+	LogLevelDef = LOG_OFF // 日志级别:off, error, warn, sql, info, all
+
+	LogFlushFreqDef = 10 // 日志刷盘时间s (>=0)
+
+	LogFlushQueueSizeDef = 100 //日志队列大小
+
+	LogBufferSizeDef = 32 * 1024 // 日志缓冲区大小 (>0)
+
+	// stat
+	StatEnableDef = false //
+
+	StatFlushFreqDef = 3 // 日志刷盘时间s (>=0)
+
+	StatSlowSqlCountDef = 100 // 慢sql top行数,(0-1000)
+
+	StatHighFreqSqlCountDef = 100 // 高频sql top行数, (0-1000)
+
+	StatSqlMaxCountDef = 100000 // sql 统计最大值(0-100000)
+
+	StatSqlRemoveModeDef = STAT_SQL_REMOVE_LATEST // 记录sql数超过最大值时,sql淘汰方式
+)
+
+var (
+	DbAliveCheckFreq = DbAliveCheckFreqDef
+
+	Locale = LocaleDef // 0:简体中文 1:英文 2:繁体中文
+
+	// log
+	LogLevel = LogLevelDef // 日志级别:off, error, warn, sql, info, all
+
+	LogDir = LogDirDef
+
+	LogFlushFreq = LogFlushFreqDef // 日志刷盘时间s (>=0)
+
+	LogFlushQueueSize = LogFlushQueueSizeDef
+
+	LogBufferSize = LogBufferSizeDef // 日志缓冲区大小 (>0)
+
+	// stat
+	StatEnable = StatEnableDef //
+
+	StatDir = StatDirDef // jdbc工作目录,所有生成的文件都在该目录下
+
+	StatFlushFreq = StatFlushFreqDef // 日志刷盘时间s (>=0)
+
+	StatSlowSqlCount = StatSlowSqlCountDef // 慢sql top行数,(0-1000)
+
+	StatHighFreqSqlCount = StatHighFreqSqlCountDef // 高频sql top行数, (0-1000)
+
+	StatSqlMaxCount = StatSqlMaxCountDef // sql 统计最大值(0-100000)
+
+	StatSqlRemoveMode = StatSqlRemoveModeDef // 记录sql数超过最大值时,sql淘汰方式
+
+	/*---------------------------------------------------------------*/
+	ServerGroupMap = make(map[string]*epGroup)
+
+	GlobalProperties = NewProperties()
+)
+
+// filePath: dm_svc.conf 文件路径
+func load(filePath string) {
+	if filePath == "" {
+		switch runtime.GOOS {
+		case "windows":
+			filePath = os.Getenv("SystemRoot") + "\\system32\\dm_svc.conf"
+		case "linux":
+			filePath = "/etc/dm_svc.conf"
+		default:
+			return
+		}
+	}
+	file, err := os.Open(filePath)
+	defer file.Close()
+	if err != nil {
+		return
+	}
+	fileReader := bufio.NewReader(file)
+
+	// GlobalProperties = NewProperties()
+	var groupProps *Properties
+	var line string //dm_svc.conf读取到的一行
+
+	for line, err = fileReader.ReadString('\n'); line != "" && (err == nil || err == io.EOF); line, err = fileReader.ReadString('\n') {
+		// 去除#标记的注释
+		if notesIndex := strings.IndexByte(line, '#'); notesIndex != -1 {
+			line = line[:notesIndex]
+		}
+		// 去除前后多余的空格
+		line = strings.TrimSpace(line)
+		if line == "" {
+			continue
+		}
+
+		if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
+			groupName := strings.ToLower(line[1 : len(line)-1])
+			dbGroup, ok := ServerGroupMap[groupName]
+			if groupName == "" || !ok {
+				continue
+			}
+			groupProps = dbGroup.props
+			if groupProps.IsNil() {
+				groupProps = NewProperties()
+				groupProps.SetProperties(GlobalProperties)
+				dbGroup.props = groupProps
+			}
+
+		} else {
+			cfgInfo := strings.Split(line, "=")
+			if len(cfgInfo) < 2 {
+				continue
+			}
+			key := strings.TrimSpace(cfgInfo[0])
+			value := strings.TrimSpace(cfgInfo[1])
+			if strings.HasPrefix(value, "(") && strings.HasSuffix(value, ")") {
+				value = strings.TrimSpace(value[1 : len(value)-1])
+			}
+			if key == "" || value == "" {
+				continue
+			}
+			// 区分属性是全局的还是组的
+			var success bool
+			if groupProps.IsNil() {
+				success = SetServerGroupProperties(GlobalProperties, key, value)
+			} else {
+				success = SetServerGroupProperties(groupProps, key, value)
+			}
+			if !success {
+				var serverGroup = parseServerName(key, value)
+				if serverGroup != nil {
+					serverGroup.props = NewProperties()
+					serverGroup.props.SetProperties(GlobalProperties)
+					ServerGroupMap[strings.ToLower(key)] = serverGroup
+				}
+			}
+		}
+	}
+}
+
+func SetServerGroupProperties(props *Properties, key string, value string) bool {
+	if util.StringUtil.EqualsIgnoreCase(key, "ADDRESS_REMAP") {
+		tmp := props.GetString(AddressRemapKey, "")
+		props.Set(AddressRemapKey, tmp+"("+value+")")
+	} else if util.StringUtil.EqualsIgnoreCase(key, "ALWAYS_ALLOW_COMMIT") {
+		props.Set(AlwayseAllowCommitKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "APP_NAME") {
+		props.Set(AppNameKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "AUTO_COMMIT") {
+		props.Set(AutoCommitKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "BATCH_ALLOW_MAX_ERRORS") {
+		props.Set(BatchAllowMaxErrorsKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "BATCH_CONTINUE_ON_ERROR") ||
+		util.StringUtil.EqualsIgnoreCase(key, "CONTINUE_BATCH_ON_ERROR") {
+		props.Set(ContinueBatchOnErrorKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "BATCH_NOT_ON_CALL") {
+		props.Set(BatchNotOnCallKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "BATCH_TYPE") {
+		props.Set(BatchTypeKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "BUF_PREFETCH") {
+		props.Set(BufPrefetchKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "CIPHER_PATH") {
+		props.Set(CipherPathKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "CLUSTER") {
+		props.Set(ClusterKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "COLUMN_NAME_UPPER_CASE") {
+		props.Set(ColumnNameUpperCaseKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "COLUMN_NAME_CASE") {
+		props.Set(ColumnNameCaseKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "COMPATIBLE_MODE") {
+		props.Set(CompatibleModeKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "COMPRESS") ||
+		util.StringUtil.EqualsIgnoreCase(key, "COMPRESS_MSG") {
+		props.Set(CompressKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "COMPRESS_ID") {
+		props.Set(CompressIdKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "CONNECT_TIMEOUT") {
+		props.Set(ConnectTimeoutKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "DO_SWITCH") ||
+		util.StringUtil.EqualsIgnoreCase(key, "AUTO_RECONNECT") {
+		props.Set(DoSwitchKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "ENABLE_RS_CACHE") {
+		props.Set(EnRsCacheKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "EP_SELECTION") {
+		props.Set(EpSelectorKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "ESCAPE_PROCESS") {
+		props.Set(EscapeProcessKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "IS_BDTA_RS") {
+		props.Set(IsBdtaRSKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "KEY_WORDS") ||
+		util.StringUtil.EqualsIgnoreCase(key, "KEYWORDS") {
+		props.Set(KeywordsKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "LANGUAGE") {
+		props.Set(LanguageKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "LOB_MODE") {
+		props.Set(LobModeKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "LOG_DIR") {
+		props.Set(LogDirKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "LOG_FLUSH_FREQ") {
+		props.Set(LogFlushFreqKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "LOG_LEVEL") {
+		props.Set(LogLevelKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "LOGIN_DSC_CTRL") {
+		props.Set(LoginDscCtrlKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "LOGIN_ENCRYPT") {
+		props.Set(LoginEncryptKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "LOGIN_MODE") {
+		props.Set(LoginModeKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "LOGIN_STATUS") {
+		props.Set(LoginStatusKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "MAX_ROWS") {
+		props.Set(MaxRowsKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "MPP_LOCAL") {
+		props.Set(MppLocalKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "OS_NAME") {
+		props.Set(OsNameKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "RS_CACHE_SIZE") {
+		props.Set(RsCacheSizeKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "RS_REFRESH_FREQ") {
+		props.Set(RsRefreshFreqKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "RW_HA") {
+		props.Set(RwHAKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "RW_IGNORE_SQL") {
+		props.Set(RwIgnoreSqlKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "RW_PERCENT") {
+		props.Set(RwPercentKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "RW_SEPARATE") {
+		props.Set(RwSeparateKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "RW_STANDBY_RECOVER_TIME") {
+		props.Set(RwStandbyRecoverTimeKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "SCHEMA") {
+		props.Set(SchemaKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "SESS_ENCODE") {
+		if IsSupportedCharset(value) {
+			props.Set("sessEncode", value)
+		}
+	} else if util.StringUtil.EqualsIgnoreCase(key, "SESSION_TIMEOUT") {
+		props.Set(SessionTimeoutKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "SOCKET_TIMEOUT") {
+		props.Set(SocketTimeoutKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "SSL_FILES_PATH") {
+		props.Set(SslFilesPathKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "STAT_DIR") {
+		props.Set(StatDirKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "STAT_ENABLE") {
+		props.Set(StatEnableKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "STAT_FLUSH_FREQ") {
+		props.Set(StatFlushFreqKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "STAT_HIGH_FREQ_SQL_COUNT") {
+		props.Set(StatHighFreqSqlCountKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "STAT_SLOW_SQL_COUNT") {
+		props.Set(StatSlowSqlCountKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "STAT_SQL_MAX_COUNT") {
+		props.Set(StatSqlMaxCountKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "STAT_SQL_REMOVE_MODE") {
+		props.Set(StatSqlRemoveModeKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "SWITCH_INTERVAL") {
+		props.Set(SwitchIntervalKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "SWITCH_TIME") ||
+		util.StringUtil.EqualsIgnoreCase(key, "SWITCH_TIMES") {
+		props.Set(SwitchTimesKey, value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "TIME_ZONE") {
+		props.Set(TimeZoneKey, value)
+		props.Set("localTimezone", value)
+	} else if util.StringUtil.EqualsIgnoreCase(key, "USER_REMAP") {
+		tmp := props.GetString(UserRemapKey, "")
+		props.Set(UserRemapKey, tmp+"("+value+")")
+	} else {
+		return false
+	}
+	return true
+}
+
+func parseServerName(name string, value string) *epGroup {
+	values := strings.Split(value, ",")
+
+	var tmpVals []string
+	var tmpName string
+	var tmpPort int
+	var svrList = make([]*ep, 0, len(values))
+
+	for _, v := range values {
+
+		var tmp *ep
+		// 先查找IPV6,以[]包括
+		begin := strings.IndexByte(v, '[')
+		end := -1
+		if begin != -1 {
+			end = strings.IndexByte(v[begin:], ']')
+		}
+		if end != -1 {
+			tmpName = v[begin+1 : end]
+
+			// port
+			if portIndex := strings.IndexByte(v[end:], ':'); portIndex != -1 {
+				tmpPort, _ = strconv.Atoi(strings.TrimSpace(v[portIndex+1:]))
+			} else {
+				tmpPort = int(DEFAULT_PORT)
+			}
+			tmp = newEP(tmpName, int32(tmpPort))
+			svrList = append(svrList, tmp)
+			continue
+		}
+		// IPV4
+		tmpVals = strings.Split(v, ":")
+		tmpName = strings.TrimSpace(tmpVals[0])
+		if len(tmpVals) >= 2 {
+			tmpPort, _ = strconv.Atoi(tmpVals[1])
+		} else {
+			tmpPort = int(DEFAULT_PORT)
+		}
+		tmp = newEP(tmpName, int32(tmpPort))
+		svrList = append(svrList, tmp)
+	}
+
+	if len(svrList) == 0 {
+		return nil
+	}
+	return newEPGroup(name, svrList)
+}
+
+func setDriverAttributes(props *Properties) {
+	if props == nil || props.Len() == 0 {
+		return
+	}
+
+	parseLanguage(props.GetString(LanguageKey, "cn"))
+	DbAliveCheckFreq = props.GetInt(DbAliveCheckFreqKey, DbAliveCheckFreqDef, 1, int(INT32_MAX))
+
+	//// log
+	//LogLevel = ParseLogLevel(props)
+	//LogDir = util.StringUtil.FormatDir(props.GetTrimString(LogDirKey, LogDirDef))
+	//LogBufferSize = props.GetInt(LogBufferSizeKey, LogBufferSizeDef, 1, int(INT32_MAX))
+	//LogFlushFreq = props.GetInt(LogFlushFreqKey, LogFlushFreqDef, 1, int(INT32_MAX))
+	//LogFlushQueueSize = props.GetInt(LogFlusherQueueSizeKey, LogFlushQueueSizeDef, 1, int(INT32_MAX))
+	//
+	//// stat
+	//StatEnable = props.GetBool(StatEnableKey, StatEnableDef)
+	//StatDir = util.StringUtil.FormatDir(props.GetTrimString(StatDirKey, StatDirDef))
+	//StatFlushFreq = props.GetInt(StatFlushFreqKey, StatFlushFreqDef, 1, int(INT32_MAX))
+	//StatHighFreqSqlCount = props.GetInt(StatHighFreqSqlCountKey, StatHighFreqSqlCountDef, 0, 1000)
+	//StatSlowSqlCount = props.GetInt(StatSlowSqlCountKey, StatSlowSqlCountDef, 0, 1000)
+	//StatSqlMaxCount = props.GetInt(StatSqlMaxCountKey, StatSqlMaxCountDef, 0, 100000)
+	//parseStatSqlRemoveMode(props)
+}
+
+func parseLanguage(value string) {
+	if util.StringUtil.EqualsIgnoreCase("cn", value) {
+		Locale = 0
+	} else if util.StringUtil.EqualsIgnoreCase("en", value) {
+		Locale = 1
+	}
+}
+
+func IsSupportedCharset(charset string) bool {
+	if util.StringUtil.EqualsIgnoreCase(ENCODING_UTF8, charset) || util.StringUtil.EqualsIgnoreCase(ENCODING_GB18030, charset) || util.StringUtil.EqualsIgnoreCase(ENCODING_EUCKR, charset) {
+		return true
+	}
+	return false
+}
+
+func ParseLogLevel(props *Properties) int {
+	logLevel := LOG_OFF
+	value := props.GetString(LogLevelKey, "")
+	if value != "" && !util.StringUtil.IsDigit(value) {
+		if util.StringUtil.EqualsIgnoreCase("debug", value) {
+			logLevel = LOG_DEBUG
+		} else if util.StringUtil.EqualsIgnoreCase("info", value) {
+			logLevel = LOG_INFO
+		} else if util.StringUtil.EqualsIgnoreCase("sql", value) {
+			logLevel = LOG_SQL
+		} else if util.StringUtil.EqualsIgnoreCase("warn", value) {
+			logLevel = LOG_WARN
+		} else if util.StringUtil.EqualsIgnoreCase("error", value) {
+			logLevel = LOG_ERROR
+		} else if util.StringUtil.EqualsIgnoreCase("off", value) {
+			logLevel = LOG_OFF
+		} else if util.StringUtil.EqualsIgnoreCase("all", value) {
+			logLevel = LOG_ALL
+		}
+	} else {
+		logLevel = props.GetInt(LogLevelKey, logLevel, LOG_OFF, LOG_INFO)
+	}
+
+	return logLevel
+}

+ 449 - 0
zzn.go

@@ -0,0 +1,449 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"database/sql"
+	"database/sql/driver"
+	"math"
+	"reflect"
+	"strings"
+	"time"
+)
+
+const (
+	INT8_MAX int8 = math.MaxInt8
+
+	INT8_MIN int8 = math.MinInt8
+
+	BYTE_MAX byte = math.MaxUint8
+
+	BYTE_MIN byte = 0
+
+	INT16_MAX int16 = math.MaxInt16
+
+	INT16_MIN int16 = math.MinInt16
+
+	UINT16_MAX uint16 = math.MaxUint16
+
+	UINT16_MIN uint16 = 0
+
+	INT32_MAX int32 = math.MaxInt32
+
+	INT32_MIN int32 = math.MinInt32
+
+	UINT32_MAX uint32 = math.MaxUint32
+
+	UINT32_MIN uint32 = 0
+
+	INT64_MAX int64 = math.MaxInt64
+
+	INT64_MIN int64 = math.MinInt64
+
+	UINT64_MAX uint64 = math.MaxUint64
+
+	UINT64_MIN uint64 = 0
+
+	FLOAT32_MAX float32 = 3.4e+38
+
+	FLOAT32_MIN float32 = -3.4e+38
+
+	BYTE_SIZE = 1
+
+	USINT_SIZE = 2
+
+	ULINT_SIZE = 4
+
+	DDWORD_SIZE = 8
+
+	LINT64_SIZE = 8
+
+	CHAR = 0
+
+	VARCHAR2 = 1
+
+	VARCHAR = 2
+
+	BIT = 3
+
+	TINYINT = 5
+
+	SMALLINT = 6
+
+	INT = 7
+
+	BIGINT = 8
+
+	DECIMAL = 9
+
+	REAL = 10
+
+	DOUBLE = 11
+
+	BLOB = 12
+
+	BOOLEAN = 13
+
+	DATE = 14
+
+	TIME = 15
+
+	DATETIME = 16
+
+	BINARY = 17
+
+	VARBINARY = 18
+
+	CLOB = 19
+
+	INTERVAL_YM = 20
+
+	INTERVAL_DT = 21
+
+	TIME_TZ = 22
+
+	DATETIME_TZ = 23
+
+	XDEC_INT32 = 24
+
+	XDEC_INT64 = 25
+
+	DATETIME2 = 26
+
+	DATETIME2_TZ = 27
+
+	NULL = 28
+
+	ANY = 31
+
+	STAR_ALL = 32
+
+	STAR = 33
+
+	RECORD = 40
+
+	TYPE = 41
+
+	TYPE_REF = 42
+
+	UNKNOWN = 54
+
+	ARRAY = 117
+
+	CLASS = 119
+
+	CURSOR = 120
+
+	PLTYPE_RECORD = 121
+
+	SARRAY = 122
+
+	CURSOR_ORACLE = -10
+
+	BIT_PREC = BYTE_SIZE
+
+	TINYINT_PREC = BYTE_SIZE
+
+	SMALLINT_PREC = USINT_SIZE
+
+	INT_PREC = ULINT_SIZE
+
+	BIGINT_PREC = LINT64_SIZE
+
+	REAL_PREC = 4
+
+	DOUBLE_PREC = 8
+
+	DATE_PREC = 3
+
+	TIME_PREC = 5
+
+	DATETIME_PREC = 8
+
+	DATETIME2_PREC = 9
+
+	TIME_TZ_PREC = TIME_PREC + 2
+
+	DATETIME_TZ_PREC = DATETIME_PREC + 2
+
+	DATETIME2_TZ_PREC = DATETIME2_PREC + 2
+
+	INTERVAL_YM_PREC = 3 * ULINT_SIZE
+
+	INTERVAL_DT_PREC = 6 * ULINT_SIZE
+
+	VARCHAR_PREC = 8188
+
+	VARBINARY_PREC = 8188
+
+	BLOB_PREC int32 = INT32_MAX
+
+	CLOB_PREC int32 = INT32_MAX
+
+	NULL_PREC = 0
+
+	LOCAL_TIME_ZONE_SCALE_MASK = 0x00001000
+
+	BFILE_PREC = 512
+
+	BFILE_SCALE = 6
+
+	COMPLEX_SCALE = 5
+
+	CURRENCY_PREC = 19
+
+	CURRENCY_SCALE = 4
+
+	LOCAL_DATETIME_SCALE_MASK int32 = 0x00001000
+
+	ORACLE_FLOAT_SCALE_MASK int32 = 0x81
+
+	ORACLE_DATE_SCALE_MASK int32 = 0x00002000
+)
+
+func isComplexType(colType int, scale int) bool {
+	return (colType == BLOB && scale == COMPLEX_SCALE) || colType == ARRAY || colType == SARRAY || colType == CLASS || colType == PLTYPE_RECORD
+}
+
+func isLocalTimeZone(colType int, scale int) bool {
+	return (colType == DATETIME || colType == DATETIME2) && (scale&LOCAL_TIME_ZONE_SCALE_MASK) != 0
+}
+
+func getLocalTimeZoneScale(colType int, scale int) int {
+	return scale & (^LOCAL_TIME_ZONE_SCALE_MASK)
+}
+
+func isFloat(colType int, scale int) bool {
+	return colType == DECIMAL && scale == int(ORACLE_FLOAT_SCALE_MASK)
+}
+
+func getFloatPrec(prec int) int {
+	return int(math.Round(float64(prec)*0.30103)) + 1
+}
+
+func getFloatScale(scale int) int {
+	return scale & (^int(ORACLE_FLOAT_SCALE_MASK))
+}
+
+var (
+	scanTypeFloat32    = reflect.TypeOf(float32(0))
+	scanTypeFloat64    = reflect.TypeOf(float64(0))
+	scanTypeBool       = reflect.TypeOf(false)
+	scanTypeInt8       = reflect.TypeOf(int8(0))
+	scanTypeInt16      = reflect.TypeOf(int16(0))
+	scanTypeInt32      = reflect.TypeOf(int32(0))
+	scanTypeInt64      = reflect.TypeOf(int64(0))
+	scanTypeNullBool   = reflect.TypeOf(sql.NullBool{})
+	scanTypeNullFloat  = reflect.TypeOf(sql.NullFloat64{})
+	scanTypeNullInt    = reflect.TypeOf(sql.NullInt64{})
+	scanTypeNullString = reflect.TypeOf(sql.NullString{})
+	scanTypeNullTime   = reflect.TypeOf(sql.NullTime{})
+	scanTypeRawBytes   = reflect.TypeOf(sql.RawBytes{})
+	scanTypeString     = reflect.TypeOf("")
+	scanTypeTime       = reflect.TypeOf(time.Now())
+	scanTypeUnknown    = reflect.TypeOf(new(interface{}))
+)
+
+func (column *column) ScanType() reflect.Type {
+
+	switch column.colType {
+	case BOOLEAN:
+		if column.nullable {
+			return scanTypeNullBool
+		}
+
+		return scanTypeBool
+
+	case BIT:
+		if strings.ToLower(column.typeName) == "boolean" {
+
+			if column.nullable {
+				return scanTypeNullBool
+			}
+
+			return scanTypeBool
+		} else {
+
+			if column.nullable {
+				return scanTypeNullInt
+			}
+			return scanTypeInt8
+		}
+
+	case TINYINT:
+		if column.nullable {
+			return scanTypeNullInt
+		}
+		return scanTypeInt8
+
+	case SMALLINT:
+		if column.nullable {
+			return scanTypeNullInt
+		}
+		return scanTypeInt16
+
+	case INT:
+		if column.nullable {
+			return scanTypeNullInt
+		}
+
+		return scanTypeInt32
+
+	case BIGINT:
+		if column.nullable {
+			return scanTypeNullInt
+		}
+		return scanTypeInt64
+
+	case REAL:
+		if column.nullable {
+			return scanTypeNullFloat
+		}
+
+		return scanTypeFloat32
+
+	case DOUBLE:
+
+		if strings.ToLower(column.typeName) == "float" {
+			if column.nullable {
+				return scanTypeNullFloat
+			}
+
+			return scanTypeFloat32
+		}
+
+		if column.nullable {
+			return scanTypeNullFloat
+		}
+
+		return scanTypeFloat64
+	case DATE, TIME, DATETIME, DATETIME2:
+		if column.nullable {
+			return scanTypeNullTime
+		}
+
+		return scanTypeTime
+
+	case DECIMAL, BINARY, VARBINARY, BLOB:
+		return scanTypeRawBytes
+
+	case CHAR, VARCHAR2, VARCHAR, CLOB:
+		if column.nullable {
+			return scanTypeNullString
+		}
+		return scanTypeString
+	}
+
+	return scanTypeUnknown
+}
+
+func (column *column) Length() (length int64, ok bool) {
+
+	switch column.colType {
+	case BINARY:
+	case VARBINARY:
+	case BLOB:
+	case CHAR:
+	case VARCHAR2:
+	case VARCHAR:
+	case CLOB:
+		return int64(column.prec), true
+	}
+
+	return int64(0), false
+}
+
+func (column *column) PrecisionScale() (precision, scale int64, ok bool) {
+	switch column.colType {
+	case DECIMAL:
+		if column.prec == 0 {
+			return 38, int64(column.scale), true
+		} else {
+			return int64(column.prec), int64(column.scale), true
+		}
+	}
+
+	return int64(0), int64(0), false
+}
+
+func (column *column) getColumnData(bytes []byte, conn *DmConnection) (driver.Value, error) {
+	if bytes == nil {
+		return nil, nil
+	}
+
+	switch column.colType {
+	case BOOLEAN:
+		return bytes[0] != 0, nil
+	case BIT:
+		if strings.ToLower(column.typeName) == "boolean" {
+			return bytes[0] != 0, nil
+		}
+
+		return int8(bytes[0]), nil
+	case TINYINT:
+		return int8(bytes[0]), nil
+	case SMALLINT:
+		return Dm_build_1.Dm_build_98(bytes, 0), nil
+	case INT:
+		return Dm_build_1.Dm_build_103(bytes, 0), nil
+	case BIGINT:
+		return Dm_build_1.Dm_build_108(bytes, 0), nil
+	case REAL:
+		return Dm_build_1.Dm_build_113(bytes, 0), nil
+	case DOUBLE:
+
+		return Dm_build_1.Dm_build_117(bytes, 0), nil
+	case DATE, TIME, DATETIME, TIME_TZ, DATETIME_TZ, DATETIME2, DATETIME2_TZ:
+		return DB2G.toTime(bytes, column, conn)
+	case INTERVAL_DT:
+		return newDmIntervalDTByBytes(bytes).String(), nil
+	case INTERVAL_YM:
+		return newDmIntervalYMByBytes(bytes).String(), nil
+	case DECIMAL:
+		tmp, err := DB2G.toDmDecimal(bytes, column, conn)
+		if err != nil {
+			return nil, err
+		}
+		return tmp.String(), nil
+
+	case BINARY, VARBINARY:
+		return bytes, nil
+	case BLOB:
+		if isComplexType(int(column.colType), int(column.scale)) {
+			return DB2G.toComplexType(bytes, column, conn)
+		}
+		blob := DB2G.toDmBlob(bytes, column, conn)
+
+		l, err := blob.GetLength()
+		if err != nil {
+			return nil, err
+		}
+		return blob.getBytes(1, int32(l))
+
+	case CHAR, VARCHAR2, VARCHAR:
+		return Dm_build_1.Dm_build_158(bytes, 0, len(bytes), conn.getServerEncoding(), conn), nil
+	case CLOB:
+		clob := DB2G.toDmClob(bytes, conn, column)
+
+		l, err := clob.GetLength()
+		if err != nil {
+			return nil, err
+		}
+		return clob.getSubString(1, int32(l))
+
+	}
+
+	return string(bytes), nil
+}
+
+func emptyStringToNil(t int32) bool {
+	switch t {
+	case BOOLEAN, BIT, TINYINT, SMALLINT, INT, BIGINT, REAL, DOUBLE, DECIMAL, DATE, TIME,
+		DATETIME, INTERVAL_DT, INTERVAL_YM, TIME_TZ, DATETIME_TZ, DATETIME2, DATETIME2_TZ:
+		return true
+	default:
+		return false
+	}
+}

+ 1389 - 0
zzo.go

@@ -0,0 +1,1389 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"strconv"
+
+	"gitee.com/chunanyong/dm/util"
+)
+
+const (
+	ARRAY_TYPE_SHORT = 1
+
+	ARRAY_TYPE_INTEGER = 2
+
+	ARRAY_TYPE_LONG = 3
+
+	ARRAY_TYPE_FLOAT = 4
+
+	ARRAY_TYPE_DOUBLE = 5
+)
+
+var TypeDataSV TypeData
+
+type InterfaceTypeData interface {
+	toBytes(x *TypeData, typeDesc *TypeDescriptor) ([]byte, error)
+}
+
+type TypeData struct {
+	m_dumyData interface{}
+
+	m_offset int
+
+	m_bufLen int
+
+	m_dataBuf []byte
+
+	m_objBlobDescBuf []byte
+
+	m_isFromBlob bool
+
+	m_packid int
+
+	m_objRefArr []interface{}
+}
+
+func newTypeData(val interface{}, dataBuf []byte) *TypeData {
+	td := new(TypeData).initTypeData()
+	td.m_dumyData = val
+	td.m_offset = 0
+	td.m_bufLen = 0
+	td.m_dataBuf = dataBuf
+	return td
+}
+
+func (td *TypeData) initTypeData() *TypeData {
+	td.m_dumyData = nil
+
+	td.m_offset = 0
+
+	td.m_bufLen = 0
+
+	td.m_dataBuf = nil
+
+	td.m_objBlobDescBuf = nil
+
+	td.m_isFromBlob = false
+
+	td.m_packid = -1
+
+	td.m_objRefArr = make([]interface{}, 0)
+
+	return td
+}
+
+func (sv TypeData) toStruct(objArr []interface{}, desc *TypeDescriptor) ([]TypeData, error) {
+	size := desc.getStrctMemSize()
+	retData := make([]TypeData, size)
+
+	for i := 0; i < size; i++ {
+
+		if objArr[i] == nil {
+			retData[i] = *newTypeData(objArr[i], nil)
+			continue
+		}
+
+		switch objArr[i].(type) {
+		case DmStruct, DmArray:
+			retData[i] = *newTypeData(objArr[i], nil)
+		default:
+			switch desc.m_fieldsObj[i].getDType() {
+			case CLASS, PLTYPE_RECORD:
+				tdArr, err := sv.toStruct(objArr[i].([]interface{}), &desc.m_fieldsObj[i])
+				if err != nil {
+					return nil, err
+				}
+
+				retData[i] = *newTypeData(newDmStructByTypeData(tdArr, &desc.m_fieldsObj[i]), nil)
+			case ARRAY, SARRAY:
+				tdArr, err := sv.toArray(objArr[i].([]interface{}), &desc.m_fieldsObj[i])
+				if err != nil {
+					return nil, err
+				}
+
+				retData[i] = *newTypeData(newDmArrayByTypeData(tdArr, &desc.m_fieldsObj[i]), nil)
+			default:
+				tdArr, err := sv.toMemberObj(objArr[i], &desc.m_fieldsObj[i])
+				if err != nil {
+					return nil, err
+				}
+				retData[i] = *tdArr
+			}
+
+		}
+	}
+	return retData, nil
+}
+
+func (sv TypeData) toArray(objArr []interface{}, desc *TypeDescriptor) ([]TypeData, error) {
+	size := len(objArr)
+	retData := make([]TypeData, size)
+	for i := 0; i < size; i++ {
+		if objArr[i] == nil {
+			retData[i] = *newTypeData(objArr[i], nil)
+			continue
+		}
+
+		switch objArr[i].(type) {
+		case DmStruct, DmArray:
+			retData[i] = *newTypeData(objArr[i], nil)
+		default:
+			switch desc.m_arrObj.getDType() {
+			case CLASS, PLTYPE_RECORD:
+				tdArr, err := sv.toStruct(objArr[i].([]interface{}), desc.m_arrObj)
+				if err != nil {
+					return nil, err
+				}
+				retData[i] = *newTypeData(newDmStructByTypeData(tdArr, desc.m_arrObj), nil)
+			case ARRAY, SARRAY:
+
+				tmp, ok := objArr[i].([]interface{})
+
+				if !ok && desc.m_arrObj.m_arrObj != nil {
+					obj, err := sv.makeupObjToArr(tmp[i], desc.m_arrObj)
+					if err != nil {
+						return nil, err
+					}
+					objArr[i] = obj
+				}
+
+				tdArr, err := sv.toArray(objArr[i].([]interface{}), desc.m_arrObj)
+				if err != nil {
+					return nil, err
+				}
+
+				retData[i] = *newTypeData(newDmArrayByTypeData(tdArr, desc.m_arrObj), nil)
+			default:
+				tdArr, err := sv.toMemberObj(objArr[i], desc.m_arrObj)
+				if err != nil {
+					return nil, err
+				}
+				retData[i] = *tdArr
+			}
+		}
+	}
+
+	return retData, nil
+}
+
+func (sv TypeData) makeupObjToArr(obj interface{}, objDesc *TypeDescriptor) ([]interface{}, error) {
+	arrType := objDesc.getDType()
+	dynamic := true
+	arrLen := 0
+	if arrType == SARRAY {
+		dynamic = false
+		arrLen = objDesc.m_length
+	}
+
+	subType := objDesc.m_arrObj.getDType()
+	if subType == BINARY || subType == VARBINARY || subType == BIT {
+
+		strRet := ""
+		switch v := obj.(type) {
+		case int:
+			strRet = strconv.FormatInt(int64(v), 2)
+		case int32:
+			strRet = strconv.FormatInt(int64(v), 2)
+		case int64:
+			strRet = strconv.FormatInt(v, 2)
+		case string:
+			strRet = v
+		default:
+			return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+		}
+		var prec int
+		if dynamic {
+			prec = len(strRet)
+		} else {
+			prec = arrLen
+		}
+
+		ret := make([]interface{}, prec)
+		rs := Dm_build_1.Dm_build_217(strRet, objDesc.getServerEncoding(), objDesc.m_conn)
+		for i := 0; i < prec; i++ {
+			ret[i] = rs[i]
+		}
+
+		return ret, nil
+	}
+
+	return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+}
+
+func (sv TypeData) toMemberObj(mem interface{}, desc *TypeDescriptor) (*TypeData, error) {
+	var bs []byte
+	scale := desc.getScale()
+	prec := desc.getPrec()
+	dtype := desc.getDType()
+	if mem == nil {
+		return newTypeData(nil, nil), nil
+	}
+
+	param := new(parameter).InitParameter()
+	param.colType = int32(dtype)
+	param.prec = int32(prec)
+	param.scale = int32(scale)
+
+	var err error
+	bs, err = G2DB.fromObject(mem, *param, desc.m_conn)
+	if err != nil {
+		return nil, err
+	}
+
+	return newTypeData(mem, bs), nil
+}
+
+func (sv TypeData) typeDataToBytes(data *TypeData, desc *TypeDescriptor) ([]byte, error) {
+	dType := desc.getDType()
+	var innerData []byte
+	var err error
+	if nil == data.m_dumyData {
+		innerData = sv.realocBuffer(nil, 0, 2)
+		Dm_build_1.Dm_build_2(innerData, 0, byte(0))
+		Dm_build_1.Dm_build_2(innerData, 1, byte(0))
+		return innerData, nil
+	}
+
+	var result []byte
+	var offset int
+	switch dType {
+	case ARRAY:
+
+		innerData, err = sv.arrayToBytes(data.m_dumyData.(*DmArray), desc)
+		if err != nil {
+			return nil, err
+		}
+
+		result = sv.realocBuffer(nil, 0, len(innerData)+BYTE_SIZE+BYTE_SIZE)
+
+		Dm_build_1.Dm_build_2(result, 0, byte(0))
+		offset = 1
+
+		Dm_build_1.Dm_build_2(result, offset, byte(1))
+		offset += 1
+		copy(result[offset:offset+len(innerData)], innerData[:len(innerData)])
+		return result, nil
+
+	case SARRAY:
+
+		innerData, err = sv.sarrayToBytes(data.m_dumyData.(*DmArray), desc)
+		if err != nil {
+			return nil, err
+		}
+		result = sv.realocBuffer(nil, 0, len(innerData)+BYTE_SIZE+BYTE_SIZE)
+
+		Dm_build_1.Dm_build_2(result, 0, byte(0))
+		offset = 1
+
+		Dm_build_1.Dm_build_2(result, offset, byte(1))
+		offset += 1
+
+		copy(result[offset:offset+len(innerData)], innerData[:len(innerData)])
+		return result, nil
+
+	case CLASS:
+
+		innerData, err = sv.objToBytes(data.m_dumyData, desc)
+		if err != nil {
+			return nil, err
+		}
+		result = sv.realocBuffer(nil, 0, len(innerData)+BYTE_SIZE+BYTE_SIZE)
+
+		Dm_build_1.Dm_build_2(result, 0, byte(0))
+		offset = 1
+
+		Dm_build_1.Dm_build_2(result, offset, byte(1))
+		offset += 1
+		copy(result[offset:offset+len(innerData)], innerData[:len(innerData)])
+		return result, nil
+
+	case PLTYPE_RECORD:
+
+		innerData, err = sv.recordToBytes(data.m_dumyData.(*DmStruct), desc)
+		if err != nil {
+			return nil, err
+		}
+		result = sv.realocBuffer(nil, 0, len(innerData)+BYTE_SIZE+BYTE_SIZE)
+
+		Dm_build_1.Dm_build_2(result, 0, byte(0))
+		offset = 1
+
+		Dm_build_1.Dm_build_2(result, offset, byte(1))
+		offset += 1
+
+		copy(result[offset:offset+len(innerData)], innerData[:len(innerData)])
+		return result, nil
+
+	case BLOB, CLOB:
+		innerData, err = sv.convertLobToBytes(data.m_dumyData, int(desc.column.colType), desc.getServerEncoding())
+
+		result = sv.realocBuffer(nil, 0, len(innerData)+BYTE_SIZE+BYTE_SIZE)
+
+		Dm_build_1.Dm_build_2(result, 0, byte(0))
+		offset = 1
+
+		Dm_build_1.Dm_build_2(result, offset, byte(1))
+		offset += 1
+		copy(result[offset:offset+len(innerData)], innerData[:len(innerData)])
+		return result, nil
+
+	case BOOLEAN:
+		innerData = sv.realocBuffer(nil, 0, 2)
+		Dm_build_1.Dm_build_2(innerData, 0, byte(0))
+		if data.m_dataBuf != nil && len(data.m_dataBuf) > 0 {
+			Dm_build_1.Dm_build_2(innerData, 1, data.m_dataBuf[0])
+		} else {
+			Dm_build_1.Dm_build_2(innerData, 1, byte(0))
+		}
+		return innerData, nil
+
+	default:
+
+		innerData = data.m_dataBuf
+		result = sv.realocBuffer(nil, 0, len(innerData)+BYTE_SIZE+BYTE_SIZE+USINT_SIZE)
+
+		Dm_build_1.Dm_build_2(result, 0, byte(0))
+		offset = 1
+
+		Dm_build_1.Dm_build_2(result, offset, byte(1))
+		offset += 1
+
+		Dm_build_1.Dm_build_12(result, offset, int16(len(innerData)))
+		offset += 2
+
+		copy(result[offset:offset+len(innerData)], innerData[:len(innerData)])
+
+		return result, nil
+	}
+}
+
+func (sv TypeData) convertLobToBytes(value interface{}, dtype int, serverEncoding string) ([]byte, error) {
+	var tmp []byte
+	var ret []byte
+	if dtype == BLOB {
+		lob, ok := value.(DmBlob)
+		if ok {
+			l, err := lob.GetLength()
+			if err != nil {
+				return nil, err
+			}
+			tmp, err = lob.getBytes(1, int32(l))
+			if err != nil {
+				return nil, err
+			}
+
+			ret = make([]byte, l+ULINT_SIZE)
+			Dm_build_1.Dm_build_17(ret, 0, int32(l))
+			copy(ret[:ULINT_SIZE:ULINT_SIZE+l], tmp[:l])
+			return ret, nil
+		}
+
+	}
+
+	if dtype == CLOB {
+		lob, ok := value.(DmClob)
+		if ok {
+			l, err := lob.GetLength()
+			if err != nil {
+				return nil, err
+			}
+
+			subString, err := lob.getSubString(1, int32(l))
+			if err != nil {
+				return nil, err
+			}
+
+			tmp = Dm_build_1.Dm_build_217(subString, serverEncoding, nil)
+			ret = make([]byte, len(tmp)+ULINT_SIZE)
+			Dm_build_1.Dm_build_17(ret, 0, int32(l))
+			copy(ret[:ULINT_SIZE:ULINT_SIZE+l], tmp[:l])
+		}
+		return ret, nil
+	}
+
+	return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+}
+
+func (sv TypeData) sarrayToBytes(data *DmArray, desc *TypeDescriptor) ([]byte, error) {
+	realLen := len(data.m_arrData)
+	results := make([][]byte, realLen)
+	var rdata []byte
+	var err error
+
+	if desc.getObjId() == 4 {
+		return sv.ctlnToBytes(data, desc)
+	}
+
+	totalLen := 0
+	for i := 0; i < realLen; i++ {
+		results[i], err = sv.typeDataToBytes(&data.m_arrData[i], desc.m_arrObj)
+		if err != nil {
+			return nil, err
+		}
+		totalLen += len(results[i])
+	}
+
+	totalLen += (ULINT_SIZE + ULINT_SIZE)
+	rdata = sv.realocBuffer(nil, 0, totalLen)
+	off := 0
+
+	Dm_build_1.Dm_build_17(rdata, off, int32(totalLen))
+	off += ULINT_SIZE
+
+	Dm_build_1.Dm_build_17(rdata, off, int32(data.m_arrDesc.getLength()))
+	off += ULINT_SIZE
+
+	for i := 0; i < realLen; i++ {
+		copy(rdata[off:off+len(results[i])], results[i][:len(results[i])])
+		off += len(results[i])
+	}
+
+	return rdata, nil
+}
+
+func (sv TypeData) ctlnToBytes(data *DmArray, desc *TypeDescriptor) ([]byte, error) {
+	results := make([][]byte, len(data.m_arrData))
+	var rdata []byte
+	var err error
+
+	var totalLen int
+	totalLen = BYTE_SIZE + ULINT_SIZE
+
+	totalLen += USINT_SIZE + USINT_SIZE + ULINT_SIZE
+
+	for i := 0; i < len(data.m_arrData); i++ {
+		results[i], err = sv.typeDataToBytes(&data.m_arrData[i], desc.m_arrObj)
+		if err != nil {
+			return nil, err
+		}
+		totalLen += len(results[i])
+	}
+
+	rdata = sv.realocBuffer(nil, 0, totalLen)
+
+	offset := 0
+
+	Dm_build_1.Dm_build_2(rdata, offset, byte(0))
+	offset += BYTE_SIZE
+
+	offset += ULINT_SIZE
+
+	Dm_build_1.Dm_build_12(rdata, offset, int16(desc.getCltnType()))
+	offset += USINT_SIZE
+
+	Dm_build_1.Dm_build_12(rdata, offset, int16(desc.m_arrObj.getDType()))
+	offset += USINT_SIZE
+
+	Dm_build_1.Dm_build_17(rdata, offset, int32(len(data.m_arrData)))
+	offset += ULINT_SIZE
+
+	for i := 0; i < len(data.m_arrData); i++ {
+		copy(rdata[offset:offset+len(results[i])], results[i][:len(results[i])])
+		offset += len(results[i])
+	}
+
+	Dm_build_1.Dm_build_17(rdata, BYTE_SIZE, int32(offset))
+
+	return rdata, nil
+}
+
+func (sv TypeData) arrayToBytes(data *DmArray, desc *TypeDescriptor) ([]byte, error) {
+	results := make([][]byte, len(data.m_arrData))
+	var rdata []byte
+	var err error
+	if desc.getObjId() == 4 {
+		return sv.ctlnToBytes(data, desc)
+	}
+
+	totalLen := 0
+	for i := 0; i < len(data.m_arrData); i++ {
+		results[i], err = sv.typeDataToBytes(&data.m_arrData[i], desc.m_arrObj)
+		if err != nil {
+			return nil, err
+		}
+		totalLen += len(results[i])
+	}
+
+	totalLen += (ULINT_SIZE + ULINT_SIZE + ULINT_SIZE + ULINT_SIZE + ULINT_SIZE)
+
+	total := data.m_objCount + data.m_strCount
+	if total > 0 {
+		totalLen += USINT_SIZE * total
+	}
+
+	rdata = sv.realocBuffer(nil, 0, totalLen)
+
+	Dm_build_1.Dm_build_17(rdata, 0, int32(totalLen))
+	offset := ULINT_SIZE
+
+	Dm_build_1.Dm_build_17(rdata, offset, int32(len(data.m_arrData)))
+	offset += ULINT_SIZE
+
+	Dm_build_1.Dm_build_17(rdata, offset, 0)
+	offset += ULINT_SIZE
+
+	Dm_build_1.Dm_build_17(rdata, offset, int32(data.m_objCount))
+	offset += ULINT_SIZE
+
+	Dm_build_1.Dm_build_17(rdata, offset, int32(data.m_strCount))
+	offset += ULINT_SIZE
+
+	for i := 0; i < total; i++ {
+		Dm_build_1.Dm_build_17(rdata, offset, int32(data.m_objStrOffs[i]))
+		offset += ULINT_SIZE
+	}
+
+	for i := 0; i < len(data.m_arrData); i++ {
+		copy(rdata[offset:offset+len(results[i])], results[i][:len(results[i])])
+		offset += len(results[i])
+	}
+
+	return rdata, nil
+}
+
+func (sv TypeData) objToBytes(data interface{}, desc *TypeDescriptor) ([]byte, error) {
+
+	switch data.(type) {
+	case *DmArray:
+		return sv.arrayToBytes(data.(*DmArray), desc)
+	default:
+		return sv.structToBytes(data.(*DmStruct), desc)
+	}
+}
+
+func (sv TypeData) structToBytes(data *DmStruct, desc *TypeDescriptor) ([]byte, error) {
+	size := desc.getStrctMemSize()
+	results := make([][]byte, size)
+	var rdata []byte
+	var err error
+
+	totalLen := 0
+	for i := 0; i < size; i++ {
+		results[i], err = sv.typeDataToBytes(&data.m_attribs[i], &desc.m_fieldsObj[i])
+		if err != nil {
+			return nil, err
+		}
+		totalLen += len(results[i])
+	}
+
+	totalLen += (BYTE_SIZE + ULINT_SIZE)
+
+	rdata = sv.realocBuffer(nil, 0, totalLen)
+	offset := 0
+
+	Dm_build_1.Dm_build_2(rdata, offset, byte(0))
+	offset += BYTE_SIZE
+
+	Dm_build_1.Dm_build_17(rdata, offset, int32(totalLen))
+	offset += ULINT_SIZE
+
+	for i := 0; i < size; i++ {
+		copy(rdata[offset:offset+len(results[i])], results[i][:len(results[i])])
+		offset += len(results[i])
+	}
+
+	return rdata, nil
+}
+
+func (sv TypeData) recordToBytes(data *DmStruct, desc *TypeDescriptor) ([]byte, error) {
+	size := desc.getStrctMemSize()
+	results := make([][]byte, size)
+	var rdata []byte
+	var err error
+
+	totalLen := 0
+	for i := 0; i < size; i++ {
+		results[i], err = sv.typeDataToBytes(&data.m_attribs[i], &desc.m_fieldsObj[i])
+		if err != nil {
+			return nil, err
+		}
+		totalLen += len(results[i])
+	}
+
+	totalLen += ULINT_SIZE
+	rdata = sv.realocBuffer(nil, 0, totalLen)
+	Dm_build_1.Dm_build_17(rdata, 0, int32(totalLen))
+
+	offset := ULINT_SIZE
+	for i := 0; i < desc.getStrctMemSize(); i++ {
+		copy(rdata[offset:offset+len(results[i])], results[i][:len(results[i])])
+		offset += len(results[i])
+	}
+
+	return rdata, nil
+}
+
+func (sv TypeData) bytesToBlob(val []byte, out *TypeData, desc *TypeDescriptor) (*TypeData, error) {
+	offset := out.m_offset
+	l := Dm_build_1.Dm_build_103(val, offset)
+	offset += ULINT_SIZE
+
+	tmp := Dm_build_1.Dm_build_152(val, offset, int(l))
+	offset += int(l)
+	out.m_offset = offset
+
+	return newTypeData(newBlobOfLocal(tmp, desc.m_conn), tmp), nil
+}
+
+func (sv TypeData) bytesToClob(val []byte, out *TypeData, desc *TypeDescriptor, serverEncoding string) (*TypeData, error) {
+	offset := out.m_offset
+	l := Dm_build_1.Dm_build_103(val, offset)
+	offset += ULINT_SIZE
+
+	tmp := Dm_build_1.Dm_build_152(val, offset, int(l))
+	offset += int(l)
+	out.m_offset = offset
+
+	return newTypeData(newClobOfLocal(Dm_build_1.Dm_build_158(tmp, 0, len(tmp), serverEncoding, desc.m_conn), desc.m_conn), tmp), nil
+}
+
+func (sv TypeData) bytesToTypeData(val []byte, out *TypeData, desc *TypeDescriptor) (*TypeData, error) {
+	offset := out.m_offset
+
+	offset += 1
+
+	null_flag := Dm_build_1.Dm_build_94(val, offset)
+	offset += 1
+
+	out.m_offset = offset
+
+	if desc.getDType() == BOOLEAN {
+		b := false
+		if null_flag != byte(0) {
+			b = true
+		}
+
+		tmp := Dm_build_1.Dm_build_152(val, offset-1, 1)
+		return newTypeData(b, tmp), nil
+	}
+
+	var retObj interface{}
+	var err error
+	var retDataBuf []byte
+	switch desc.getDType() {
+	case CLASS:
+		if null_flag&byte(1) != byte(0) {
+			retObj, err = sv.bytesToObj(val, out, desc)
+			if err != nil {
+				return nil, err
+			}
+
+			if out.m_offset > offset {
+				retDataBuf = Dm_build_1.Dm_build_152(val, offset, out.m_offset-offset)
+			}
+
+			return newTypeData(retObj, retDataBuf), nil
+		} else {
+			return newTypeData(nil, nil), nil
+		}
+
+	case ARRAY:
+		if (null_flag & byte(1)) != byte(0) {
+			retObj, err = sv.bytesToArray(val, out, desc)
+			if err != nil {
+				return nil, err
+			}
+
+			if out.m_offset > offset {
+				retDataBuf = Dm_build_1.Dm_build_152(val, offset, out.m_offset-offset)
+			}
+
+			return newTypeData(retObj, retDataBuf), nil
+		} else {
+			return newTypeData(nil, nil), nil
+		}
+
+	case PLTYPE_RECORD:
+		if (null_flag & byte(1)) != byte(0) {
+			retObj, err = sv.bytesToRecord(val, out, desc)
+			if err != nil {
+				return nil, err
+			}
+
+			if out.m_offset > offset {
+				retDataBuf = Dm_build_1.Dm_build_152(val, offset, out.m_offset-offset)
+			}
+
+			return newTypeData(retObj, retDataBuf), nil
+		} else {
+			return newTypeData(nil, nil), nil
+		}
+
+	case SARRAY:
+		if (null_flag & byte(1)) != byte(0) {
+			retObj, err = sv.bytesToSArray(val, out, desc)
+			if err != nil {
+				return nil, err
+			}
+
+			if out.m_offset > offset {
+				retDataBuf = Dm_build_1.Dm_build_152(val, offset, out.m_offset-offset)
+			}
+
+			return newTypeData(retObj, retDataBuf), nil
+		} else {
+			return newTypeData(nil, nil), nil
+		}
+
+	case BLOB:
+		if null_flag&byte(1) != byte(0) {
+			return sv.bytesToBlob(val, out, desc)
+		} else {
+			return newTypeData(nil, nil), nil
+		}
+
+	case CLOB:
+		if null_flag&byte(1) != byte(0) {
+			return sv.bytesToClob(val, out, desc, desc.getServerEncoding())
+		} else {
+			return newTypeData(nil, nil), nil
+		}
+
+	default:
+		if null_flag&byte(1) != byte(0) {
+			return sv.convertBytes2BaseData(val, out, desc)
+		} else {
+			return newTypeData(nil, nil), nil
+		}
+
+	}
+}
+
+func (sv TypeData) checkObjExist(val []byte, out *TypeData) bool {
+	offset := out.m_offset
+	exist_flag := Dm_build_1.Dm_build_94(val, offset)
+	offset += 1
+
+	out.m_offset = offset
+
+	if exist_flag == byte(1) {
+		return true
+	}
+
+	out.m_offset += ULINT_SIZE
+	return false
+}
+
+func (sv TypeData) findObjByPackId(val []byte, out *TypeData) (*DmStruct, error) {
+	offset := out.m_offset
+
+	pack_id := int(Dm_build_1.Dm_build_103(val, offset))
+	offset += ULINT_SIZE
+
+	out.m_offset = offset
+
+	if pack_id < 0 || pack_id > out.m_packid {
+		return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+	}
+
+	return out.m_objRefArr[pack_id].(*DmStruct), nil
+}
+
+func (sv TypeData) addObjToRefArr(out *TypeData, objToAdd interface{}) {
+	out.m_objRefArr = append(out.m_objRefArr, objToAdd)
+	out.m_packid++
+}
+
+func (sv TypeData) checkObjClnt(desc *TypeDescriptor) bool {
+	return desc.m_objId == 4
+}
+
+func (sv TypeData) bytesToObj_EXACT(val []byte, out *TypeData, desc *TypeDescriptor) (*DmStruct, error) {
+	strOut := newDmStructByTypeData(nil, desc)
+	var sub_desc *TypeDescriptor
+	offset := out.m_offset
+
+	size := desc.getStrctMemSize()
+
+	out.m_offset = offset
+
+	strOut.m_attribs = make([]TypeData, size)
+	for i := 0; i < size; i++ {
+		sub_desc = &desc.m_fieldsObj[i]
+		tmp, err := sv.bytesToTypeData(val, out, sub_desc)
+		if err != nil {
+			return nil, err
+		}
+		strOut.m_attribs[i] = *tmp
+	}
+
+	strOut.m_dataBuf = Dm_build_1.Dm_build_152(val, offset, out.m_offset-offset)
+
+	return strOut, nil
+}
+
+func (sv TypeData) bytesToNestTab(val []byte, out *TypeData, desc *TypeDescriptor) (*DmArray, error) {
+	offset := out.m_offset
+
+	offset += USINT_SIZE
+
+	count := Dm_build_1.Dm_build_103(val, offset)
+	offset += ULINT_SIZE
+
+	out.m_offset = offset
+
+	arrOut := newDmArrayByTypeData(nil, desc)
+	arrOut.m_itemCount = int(count)
+	arrOut.m_arrData = make([]TypeData, count)
+	for i := 0; i < int(count); i++ {
+		tmp, err := sv.bytesToTypeData(val, out, desc.m_arrObj)
+		if err != nil {
+			return nil, err
+		}
+		arrOut.m_arrData[i] = *tmp
+	}
+
+	arrOut.m_dataBuf = Dm_build_1.Dm_build_152(val, offset, out.m_offset-offset)
+
+	return arrOut, nil
+}
+
+func (sv TypeData) bytesToClnt(val []byte, out *TypeData, desc *TypeDescriptor) (*DmArray, error) {
+	var array *DmArray
+
+	offset := out.m_offset
+
+	cltn_type := Dm_build_1.Dm_build_98(val, offset)
+	offset += USINT_SIZE
+
+	out.m_offset = offset
+	switch cltn_type {
+	case CLTN_TYPE_IND_TABLE:
+		return nil, ECGO_UNSUPPORTED_TYPE.throw()
+
+	case CLTN_TYPE_NST_TABLE, CLTN_TYPE_VARRAY:
+		return sv.bytesToNestTab(val, out, desc)
+	}
+
+	return array, nil
+}
+
+func (sv TypeData) bytesToObj(val []byte, out *TypeData, desc *TypeDescriptor) (interface{}, error) {
+	var retObj interface{}
+	var err error
+	if out == nil {
+		out = newTypeData(nil, nil)
+	}
+
+	if sv.checkObjExist(val, out) {
+		retObj, err = sv.findObjByPackId(val, out)
+		if err != nil {
+			return nil, err
+		}
+	} else {
+		sv.addObjToRefArr(out, retObj)
+	}
+
+	if sv.checkObjClnt(desc) {
+		retObj, err = sv.bytesToClnt(val, out, desc)
+		if err != nil {
+			return nil, err
+		}
+	} else {
+		retObj, err = sv.bytesToObj_EXACT(val, out, desc)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return retObj, nil
+}
+
+func (sv TypeData) bytesToArray(val []byte, out *TypeData, desc *TypeDescriptor) (*DmArray, error) {
+	arrOut := newDmArrayByTypeData(nil, desc)
+	if out == nil {
+		out = newTypeData(nil, nil)
+	}
+
+	offset := out.m_offset
+
+	arrOut.m_bufLen = int(Dm_build_1.Dm_build_103(val, offset))
+	offset += 4
+
+	arrOut.m_itemCount = int(Dm_build_1.Dm_build_103(val, offset))
+	offset += ULINT_SIZE
+
+	arrOut.m_itemSize = int(Dm_build_1.Dm_build_103(val, offset))
+	offset += ULINT_SIZE
+
+	arrOut.m_objCount = int(Dm_build_1.Dm_build_103(val, offset))
+	offset += ULINT_SIZE
+
+	arrOut.m_strCount = int(Dm_build_1.Dm_build_103(val, offset))
+	offset += ULINT_SIZE
+
+	total := arrOut.m_objCount + arrOut.m_strCount
+	arrOut.m_objStrOffs = make([]int, total)
+	for i := 0; i < total; i++ {
+		arrOut.m_objStrOffs[i] = int(Dm_build_1.Dm_build_103(val, offset))
+		offset += 4
+	}
+
+	out.m_offset = offset
+
+	arrOut.m_arrData = make([]TypeData, arrOut.m_itemCount)
+	for i := 0; i < arrOut.m_itemCount; i++ {
+		tmp, err := sv.bytesToTypeData(val, out, desc.m_arrObj)
+		if err != nil {
+			return nil, err
+		}
+		arrOut.m_arrData[i] = *tmp
+	}
+
+	arrOut.m_dataBuf = Dm_build_1.Dm_build_152(val, offset, out.m_offset-offset)
+
+	return arrOut, nil
+}
+
+func (sv TypeData) bytesToSArray(val []byte, out *TypeData, desc *TypeDescriptor) (*DmArray, error) {
+	if out == nil {
+		out = newTypeData(nil, nil)
+	}
+
+	offset := out.m_offset
+
+	arrOut := newDmArrayByTypeData(nil, desc)
+	arrOut.m_bufLen = int(Dm_build_1.Dm_build_103(val, offset))
+	offset += ULINT_SIZE
+
+	arrOut.m_itemCount = int(Dm_build_1.Dm_build_103(val, offset))
+	offset += ULINT_SIZE
+
+	out.m_offset = offset
+
+	arrOut.m_arrData = make([]TypeData, arrOut.m_itemCount)
+	for i := 0; i < arrOut.m_itemCount; i++ {
+		tmp, err := sv.bytesToTypeData(val, out, desc.m_arrObj)
+		if err != nil {
+			return nil, err
+		}
+		arrOut.m_arrData[i] = *tmp
+	}
+
+	arrOut.m_dataBuf = Dm_build_1.Dm_build_152(val, offset, out.m_offset-offset)
+
+	return arrOut, nil
+}
+
+func (sv TypeData) bytesToRecord(val []byte, out *TypeData, desc *TypeDescriptor) (*DmStruct, error) {
+	if out == nil {
+		out = newTypeData(nil, nil)
+	}
+
+	offset := out.m_offset
+
+	strOut := newDmStructByTypeData(nil, desc)
+	strOut.m_bufLen = int(Dm_build_1.Dm_build_103(val, offset))
+	offset += ULINT_SIZE
+
+	out.m_offset = offset
+
+	strOut.m_attribs = make([]TypeData, desc.getStrctMemSize())
+	for i := 0; i < desc.getStrctMemSize(); i++ {
+		tmp, err := sv.bytesToTypeData(val, out, &desc.m_fieldsObj[i])
+		if err != nil {
+			return nil, err
+		}
+		strOut.m_attribs[i] = *tmp
+	}
+
+	strOut.m_dataBuf = Dm_build_1.Dm_build_152(val, offset, out.m_offset-offset)
+
+	return strOut, nil
+}
+
+func (sv TypeData) objBlob_GetChkBuf(buf []byte, typeData *TypeData) {
+
+	offset := 4
+
+	l := int(Dm_build_1.Dm_build_103(buf, offset))
+	offset += ULINT_SIZE
+
+	typeData.m_objBlobDescBuf = Dm_build_1.Dm_build_152(buf, offset, l)
+	offset += l
+
+	typeData.m_isFromBlob = true
+
+	typeData.m_offset = offset
+}
+
+func (sv TypeData) objBlobToObj(lob *DmBlob, desc *TypeDescriptor) (interface{}, error) {
+	typeData := newTypeData(nil, nil)
+	loblen, err := lob.GetLength()
+	if err != nil {
+		return nil, err
+	}
+
+	buf, err := lob.getBytes(1, int32(loblen))
+	if err != nil {
+		return nil, err
+	}
+
+	sv.objBlob_GetChkBuf(buf, typeData)
+
+	return sv.bytesToObj(buf, typeData, desc)
+}
+
+func (sv TypeData) objBlobToBytes(lobBuf []byte, desc *TypeDescriptor) ([]byte, error) {
+	l := len(lobBuf)
+	offset := 0
+
+	magic := Dm_build_1.Dm_build_103(lobBuf, offset)
+	offset += ULINT_SIZE
+
+	if OBJ_BLOB_MAGIC != magic {
+		return nil, ECGO_INVALID_OBJ_BLOB.throw()
+	}
+
+	descLen := int(Dm_build_1.Dm_build_103(lobBuf, offset))
+	offset += ULINT_SIZE
+	descBuf := Dm_build_1.Dm_build_152(lobBuf, offset, descLen)
+	tmp, err := desc.getClassDescChkInfo()
+	if err != nil {
+		return nil, err
+	}
+	if !util.SliceEquals(descBuf, tmp) {
+		return nil, ECGO_INVALID_OBJ_BLOB.throw()
+	}
+	offset += descLen
+
+	ret := make([]byte, l-offset)
+	copy(ret[:len(ret)], lobBuf[offset:offset+len(ret)])
+	return ret, nil
+}
+
+func (sv TypeData) realocBuffer(oldBuf []byte, offset int, needLen int) []byte {
+	var retBuf []byte
+
+	if oldBuf == nil {
+		return make([]byte, needLen)
+	} else if needLen+offset > len(oldBuf) {
+		retBuf = make([]byte, len(oldBuf)+needLen)
+		copy(retBuf[:offset], oldBuf[:offset])
+	} else {
+		retBuf = oldBuf
+	}
+
+	return retBuf
+}
+
+func (sv TypeData) convertBytes2BaseData(val []byte, out *TypeData, desc *TypeDescriptor) (*TypeData, error) {
+	offset := out.m_offset
+	isNull := false
+	valueLen := int(Dm_build_1.Dm_build_125(val, offset))
+	offset += USINT_SIZE
+
+	if valueLen == int(Dm_build_1022) {
+		valueLen = 0
+		isNull = true
+	}
+
+	if -1 == valueLen {
+		valueLen = int(Dm_build_1.Dm_build_103(val, offset))
+		offset += ULINT_SIZE
+	}
+
+	if isNull {
+		out.m_offset = offset
+		return newTypeData(nil, nil), nil
+	}
+
+	var tmpObj interface{}
+	var err error
+	temp := Dm_build_1.Dm_build_152(val, offset, valueLen)
+	offset += valueLen
+	out.m_offset = offset
+
+	tmpObj, err = DB2G.toObject(temp, desc.column, desc.m_conn)
+	if err != nil {
+		return nil, err
+	}
+	return newTypeData(tmpObj, temp), nil
+}
+
+func (td *TypeData) toJavaArray(arr *DmArray, index int64, l int, dType int) (interface{}, error) {
+	if arr.m_objArray != nil {
+		return arr.m_objArray, nil
+	}
+
+	var nr = make([]interface{}, l)
+	var tempData *TypeData
+	switch dType {
+	case CHAR, VARCHAR, VARCHAR2:
+		for i := 0; i < l; i++ {
+			tempData = &arr.m_arrData[index+int64(i)]
+			if tempData != nil && tempData.m_dumyData != nil {
+				nr[i] = tempData.m_dumyData
+			}
+		}
+	case BIT, TINYINT:
+		for i := 0; i < l; i++ {
+			tempData = &arr.m_arrData[index+int64(i)]
+			if tempData != nil && tempData.m_dumyData != nil {
+				nr[i] = tempData.m_dumyData
+			} else {
+				nr[i] = nil
+			}
+		}
+
+	case BINARY, VARBINARY:
+		for i := 0; i < l; i++ {
+			tempData = &arr.m_arrData[index+int64(i)]
+			if tempData != nil && tempData.m_dumyData != nil {
+				nr[i] = tempData.m_dumyData
+			}
+		}
+
+	case BOOLEAN:
+		for i := 0; i < l; i++ {
+			tempData = &arr.m_arrData[index+int64(i)]
+			if tempData != nil && tempData.m_dumyData != nil {
+				nr[i] = tempData.m_dumyData
+			} else {
+				nr[i] = nil
+			}
+		}
+
+	case SMALLINT:
+		for i := 0; i < l; i++ {
+			tempData = &arr.m_arrData[index+int64(i)]
+			if tempData != nil && tempData.m_dumyData != nil {
+				nr[i] = tempData.m_dumyData
+			} else {
+				nr[i] = nil
+			}
+		}
+
+	case INT:
+		for i := 0; i < l; i++ {
+			tempData = &arr.m_arrData[index+int64(i)]
+			if tempData != nil && tempData.m_dumyData != nil {
+				nr[i] = tempData.m_dumyData
+			} else {
+				nr[i] = nil
+			}
+		}
+
+	case BIGINT:
+		for i := 0; i < l; i++ {
+			tempData = &arr.m_arrData[index+int64(i)]
+			if tempData != nil && tempData.m_dumyData != nil {
+				nr[i] = tempData.m_dumyData
+			} else {
+				nr[i] = nil
+			}
+		}
+
+	case DECIMAL:
+
+		for i := 0; i < l; i++ {
+			tempData = &arr.m_arrData[index+int64(i)]
+			if tempData != nil && tempData.m_dumyData != nil {
+				nr[i] = tempData.m_dumyData
+			}
+		}
+	case REAL:
+		for i := 0; i < l; i++ {
+			tempData = &arr.m_arrData[index+int64(i)]
+			if tempData != nil && tempData.m_dumyData != nil {
+				nr[i] = tempData.m_dumyData
+			} else {
+				nr[i] = nil
+			}
+		}
+
+	case DOUBLE:
+		for i := 0; i < l; i++ {
+			tempData = &arr.m_arrData[index+int64(i)]
+			if tempData != nil && tempData.m_dumyData != nil {
+				nr[i] = tempData.m_dumyData
+			} else {
+				nr[i] = nil
+			}
+		}
+
+	case DATE, TIME, DATETIME, TIME_TZ, DATETIME_TZ, DATETIME2, DATETIME2_TZ:
+		for i := 0; i < l; i++ {
+			tempData = &arr.m_arrData[index+int64(i)]
+			if tempData != nil && tempData.m_dumyData != nil {
+				nr[i] = tempData.m_dumyData
+			}
+		}
+
+	case INTERVAL_YM:
+		for i := 0; i < l; i++ {
+			tempData = &arr.m_arrData[index+int64(i)]
+			if tempData != nil && tempData.m_dumyData != nil {
+				nr[i] = tempData.m_dumyData
+			}
+		}
+
+	case INTERVAL_DT:
+		for i := 0; i < l; i++ {
+			tempData = &arr.m_arrData[index+int64(i)]
+			if tempData != nil && tempData.m_dumyData != nil {
+				nr[i] = tempData.m_dumyData
+			}
+		}
+
+	case PLTYPE_RECORD, CLASS, ARRAY, SARRAY:
+		for i := 0; i < l; i++ {
+			tempData = &arr.m_arrData[index+int64(i)]
+			if tempData != nil {
+				nr[i] = tempData.m_dumyData
+			}
+		}
+
+	case BLOB:
+		for i := 0; i < l; i++ {
+			tempData = &arr.m_arrData[index+int64(i)]
+			if tempData != nil && tempData.m_dumyData != nil {
+				nr[i] = tempData.m_dumyData
+			}
+		}
+
+	case CLOB:
+		for i := 0; i < l; i++ {
+			tempData = &arr.m_arrData[index+int64(i)]
+			if tempData != nil && tempData.m_dumyData != nil {
+				nr[i] = tempData.m_dumyData
+			}
+		}
+
+	default:
+		return nil, ECGO_UNSUPPORTED_TYPE.throw()
+	}
+
+	return nr, nil
+}
+
+func (td *TypeData) toNumericArray(arr *DmArray, index int64, l int, flag int) (interface{}, error) {
+	if nil == arr.m_objArray {
+		return nil, nil
+	}
+
+	var retObj interface{}
+	switch arr.m_objArray.(type) {
+	case []int16:
+		if flag == ARRAY_TYPE_SHORT {
+			ret := make([]int16, l)
+			copy(ret[:l], arr.m_objArray.([]int16)[index:index+int64(l)])
+			retObj = ret
+		}
+	case []int:
+		if flag == ARRAY_TYPE_INTEGER {
+			ret := make([]int, l)
+			copy(ret[:l], arr.m_objArray.([]int)[index:index+int64(l)])
+			retObj = ret
+		}
+	case []int64:
+		if flag == ARRAY_TYPE_LONG {
+			ret := make([]int64, l)
+			copy(ret[:l], arr.m_objArray.([]int64)[index:index+int64(l)])
+			retObj = ret
+		}
+	case []float32:
+		if flag == ARRAY_TYPE_FLOAT {
+			ret := make([]float32, l)
+			copy(ret[:l], arr.m_objArray.([]float32)[index:index+int64(l)])
+			retObj = ret
+		}
+	case []float64:
+		if flag == ARRAY_TYPE_DOUBLE {
+			ret := make([]float64, l)
+			copy(ret[:l], arr.m_objArray.([]float64)[index:index+int64(l)])
+			retObj = ret
+		}
+	default:
+		return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+	}
+
+	return retObj, nil
+}
+
+func (td *TypeData) toJavaArrayByDmStruct(st *DmStruct) ([]interface{}, error) {
+	attrsData := st.getAttribsTypeData()
+	if nil == st.getAttribsTypeData() || len(st.getAttribsTypeData()) <= 0 {
+		return nil, nil
+	}
+
+	fields := st.m_strctDesc.getItemsDesc()
+	if len(attrsData) != len(fields) {
+		return nil, ECGO_STRUCT_MEM_NOT_MATCH.throw()
+	}
+
+	out := make([]interface{}, len(fields))
+	for i := 0; i < len(fields); i++ {
+		out[i] = attrsData[i].m_dumyData
+	}
+
+	return out, nil
+}
+
+func (td *TypeData) toBytesFromDmArray(x *DmArray, typeDesc *TypeDescriptor) ([]byte, error) {
+	var err error
+	desc, err := typeDesc.getClassDescChkInfo()
+	if err != nil {
+		return nil, err
+	}
+	var data []byte
+	switch typeDesc.getDType() {
+	case ARRAY:
+		data, err = TypeDataSV.arrayToBytes(x, typeDesc)
+		if err != nil {
+			return nil, err
+		}
+	case SARRAY:
+		data, err = TypeDataSV.sarrayToBytes(x, typeDesc)
+		if err != nil {
+			return nil, err
+		}
+	case PLTYPE_RECORD:
+		return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+	case CLASS:
+		data, err = TypeDataSV.objToBytes(x, typeDesc)
+		if err != nil {
+			return nil, err
+		}
+	}
+	ret := make([]byte, ULINT_SIZE+ULINT_SIZE+len(desc)+len(data))
+	Dm_build_1.Dm_build_17(ret, 0, OBJ_BLOB_MAGIC)
+	Dm_build_1.Dm_build_17(ret, ULINT_SIZE, int32(len(desc)))
+	copy(ret[ULINT_SIZE+ULINT_SIZE:ULINT_SIZE+ULINT_SIZE+len(desc)], desc[:len(desc)])
+	copy(ret[ULINT_SIZE+ULINT_SIZE+len(desc):ULINT_SIZE+ULINT_SIZE+len(desc)+len(data)], data[:len(data)])
+	return ret, nil
+}
+
+func (td *TypeData) toBytesFromDmStruct(x *DmStruct, typeDesc *TypeDescriptor) ([]byte, error) {
+	var err error
+	desc, err := typeDesc.getClassDescChkInfo()
+	if err != nil {
+		return nil, err
+	}
+	var data []byte
+	switch typeDesc.getDType() {
+	case ARRAY:
+		return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+	case SARRAY:
+		return nil, ECGO_DATA_CONVERTION_ERROR.throw()
+	case PLTYPE_RECORD:
+		data, err = TypeDataSV.recordToBytes(x, typeDesc)
+		if err != nil {
+			return nil, err
+		}
+	case CLASS:
+		data, err = TypeDataSV.objToBytes(x, typeDesc)
+		if err != nil {
+			return nil, err
+		}
+	}
+	ret := make([]byte, ULINT_SIZE+ULINT_SIZE+len(desc)+len(data))
+	Dm_build_1.Dm_build_17(ret, 0, OBJ_BLOB_MAGIC)
+	Dm_build_1.Dm_build_17(ret, ULINT_SIZE, int32(len(desc)))
+	copy(ret[ULINT_SIZE+ULINT_SIZE:ULINT_SIZE+ULINT_SIZE+len(desc)], desc[:len(desc)])
+	copy(ret[ULINT_SIZE+ULINT_SIZE+len(desc):ULINT_SIZE+ULINT_SIZE+len(desc)+len(data)], data[:len(data)])
+	return ret, nil
+}

+ 763 - 0
zzp.go

@@ -0,0 +1,763 @@
+/*
+ * Copyright (c) 2000-2018, 达梦数据库有限公司.
+ * All rights reserved.
+ */
+package dm
+
+import (
+	"database/sql/driver"
+)
+
+const (
+	OBJ_BLOB_MAGIC = 78111999
+
+	CLTN_TYPE_IND_TABLE = 3
+
+	CLTN_TYPE_NST_TABLE = 2
+
+	CLTN_TYPE_VARRAY = 1
+)
+
+type TypeDescriptor struct {
+	column *column
+
+	m_sqlName *sqlName
+
+	m_objId int
+
+	m_objVersion int
+
+	m_outerId int
+
+	m_outerVer int
+
+	m_subId int
+
+	m_cltnType int
+
+	m_maxCnt int
+
+	m_length int
+
+	m_size int
+
+	m_conn *DmConnection
+
+	m_serverEncoding string
+
+	m_arrObj *TypeDescriptor
+
+	m_fieldsObj []TypeDescriptor
+
+	m_descBuf []byte
+}
+
+func newTypeDescriptorWithFulName(fulName string, conn *DmConnection) *TypeDescriptor {
+	td := new(TypeDescriptor)
+	td.init()
+	td.m_sqlName = newSqlNameByFulName(fulName)
+	td.m_conn = conn
+	return td
+}
+
+func newTypeDescriptor(conn *DmConnection) *TypeDescriptor {
+	td := new(TypeDescriptor)
+	td.init()
+	td.m_sqlName = newSqlNameByConn(conn)
+	td.m_conn = conn
+	return td
+}
+
+func (typeDescriptor *TypeDescriptor) init() {
+	typeDescriptor.column = new(column).InitColumn()
+
+	typeDescriptor.m_sqlName = nil
+
+	typeDescriptor.m_objId = -1
+
+	typeDescriptor.m_objVersion = -1
+
+	typeDescriptor.m_outerId = 0
+
+	typeDescriptor.m_outerVer = 0
+
+	typeDescriptor.m_subId = 0
+
+	typeDescriptor.m_cltnType = 0
+
+	typeDescriptor.m_maxCnt = 0
+
+	typeDescriptor.m_length = 0
+
+	typeDescriptor.m_size = 0
+
+	typeDescriptor.m_conn = nil
+
+	typeDescriptor.m_serverEncoding = ""
+
+	typeDescriptor.m_arrObj = nil
+
+	typeDescriptor.m_fieldsObj = nil
+
+	typeDescriptor.m_descBuf = nil
+}
+
+func (typeDescriptor *TypeDescriptor) parseDescByName() error {
+	sql := "BEGIN ? = SF_DESCRIBE_TYPE(?); END;"
+
+	params := make([]driver.Value, 2)
+	params[1] = typeDescriptor.m_sqlName.m_fulName
+
+	rs, err := typeDescriptor.m_conn.query(sql, params)
+	if err != nil {
+		return err
+	}
+	rs.close()
+	l, err := params[0].(*DmBlob).GetLength()
+	if err != nil {
+		return err
+	}
+
+	buf, err := params[0].(*DmBlob).getBytes(1, int32(l))
+	if err != nil {
+		return err
+	}
+	typeDescriptor.m_serverEncoding = typeDescriptor.m_conn.getServerEncoding()
+	err = typeDescriptor.unpack(Dm_build_366(buf))
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func (typeDescriptor *TypeDescriptor) getFulName() (string, error) {
+	return typeDescriptor.m_sqlName.getFulName()
+}
+
+func (typeDescriptor *TypeDescriptor) getDType() int {
+	return int(typeDescriptor.column.colType)
+}
+
+func (typeDescriptor *TypeDescriptor) getPrec() int {
+	return int(typeDescriptor.column.prec)
+}
+
+func (typeDescriptor *TypeDescriptor) getScale() int {
+	return int(typeDescriptor.column.scale)
+}
+
+func (typeDescriptor *TypeDescriptor) getServerEncoding() string {
+	if typeDescriptor.m_serverEncoding == "" {
+		return typeDescriptor.m_conn.getServerEncoding()
+	} else {
+		return typeDescriptor.m_serverEncoding
+	}
+}
+
+func (typeDescriptor *TypeDescriptor) getObjId() int {
+	return typeDescriptor.m_objId
+}
+
+func (typeDescriptor *TypeDescriptor) getStaticArrayLength() int {
+	return typeDescriptor.m_length
+}
+
+func (typeDescriptor *TypeDescriptor) getStrctMemSize() int {
+	return typeDescriptor.m_size
+}
+
+func (typeDescriptor *TypeDescriptor) getOuterId() int {
+	return typeDescriptor.m_outerId
+}
+
+func (typeDescriptor *TypeDescriptor) getCltnType() int {
+	return typeDescriptor.m_cltnType
+}
+
+func (typeDescriptor *TypeDescriptor) getMaxCnt() int {
+	return typeDescriptor.m_maxCnt
+}
+
+func getPackSize(typeDesc *TypeDescriptor) (int, error) {
+	len := 0
+
+	switch typeDesc.column.colType {
+	case ARRAY, SARRAY:
+		return getPackArraySize(typeDesc)
+
+	case CLASS:
+		return getPackClassSize(typeDesc)
+
+	case PLTYPE_RECORD:
+		return getPackRecordSize(typeDesc)
+	}
+
+	len += ULINT_SIZE
+
+	len += ULINT_SIZE
+
+	len += ULINT_SIZE
+
+	return len, nil
+}
+
+func pack(typeDesc *TypeDescriptor, msg *Dm_build_361) error {
+	switch typeDesc.column.colType {
+	case ARRAY, SARRAY:
+		return packArray(typeDesc, msg)
+	case CLASS:
+		return packClass(typeDesc, msg)
+	case PLTYPE_RECORD:
+		return packRecord(typeDesc, msg)
+	}
+
+	msg.Dm_build_416(typeDesc.column.colType)
+
+	msg.Dm_build_416(typeDesc.column.prec)
+
+	msg.Dm_build_416(typeDesc.column.scale)
+	return nil
+}
+
+func getPackArraySize(arrDesc *TypeDescriptor) (int, error) {
+	l := 0
+
+	l += ULINT_SIZE
+
+	name := arrDesc.m_sqlName.m_name
+	l += USINT_SIZE
+
+	serverEncoding := arrDesc.getServerEncoding()
+	ret := Dm_build_1.Dm_build_217(name, serverEncoding, arrDesc.m_conn)
+	l += len(ret)
+
+	l += ULINT_SIZE
+
+	l += ULINT_SIZE
+
+	l += ULINT_SIZE
+
+	i, err := getPackSize(arrDesc.m_arrObj)
+	if err != nil {
+		return 0, err
+	}
+
+	l += i
+
+	return l, nil
+}
+
+func packArray(arrDesc *TypeDescriptor, msg *Dm_build_361) error {
+
+	msg.Dm_build_416(arrDesc.column.colType)
+
+	msg.Dm_build_472(arrDesc.m_sqlName.m_name, arrDesc.getServerEncoding(), arrDesc.m_conn)
+
+	msg.Dm_build_416(int32(arrDesc.m_objId))
+
+	msg.Dm_build_416(int32(arrDesc.m_objVersion))
+
+	msg.Dm_build_416(int32(arrDesc.m_length))
+
+	return pack(arrDesc.m_arrObj, msg)
+}
+
+func packRecord(strctDesc *TypeDescriptor, msg *Dm_build_361) error {
+
+	msg.Dm_build_416(strctDesc.column.colType)
+
+	msg.Dm_build_472(strctDesc.m_sqlName.m_name, strctDesc.getServerEncoding(), strctDesc.m_conn)
+
+	msg.Dm_build_416(int32(strctDesc.m_objId))
+
+	msg.Dm_build_416(int32(strctDesc.m_objVersion))
+
+	msg.Dm_build_412(int16(strctDesc.m_size))
+
+	for i := 0; i < strctDesc.m_size; i++ {
+		err := pack(&strctDesc.m_fieldsObj[i], msg)
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func getPackRecordSize(strctDesc *TypeDescriptor) (int, error) {
+	l := 0
+
+	l += ULINT_SIZE
+
+	name := strctDesc.m_sqlName.m_name
+	l += USINT_SIZE
+
+	serverEncoding := strctDesc.getServerEncoding()
+	ret := Dm_build_1.Dm_build_217(name, serverEncoding, strctDesc.m_conn)
+	l += len(ret)
+
+	l += ULINT_SIZE
+
+	l += ULINT_SIZE
+
+	l += USINT_SIZE
+
+	for i := 0; i < strctDesc.m_size; i++ {
+		i, err := getPackSize(&strctDesc.m_fieldsObj[i])
+		if err != nil {
+			return 0, err
+		}
+		l += i
+	}
+
+	return l, nil
+}
+
+func getPackClassSize(strctDesc *TypeDescriptor) (int, error) {
+	l := 0
+
+	l += ULINT_SIZE
+
+	name := strctDesc.m_sqlName.m_name
+	l += USINT_SIZE
+
+	serverEncoding := strctDesc.getServerEncoding()
+	ret := Dm_build_1.Dm_build_217(name, serverEncoding, strctDesc.m_conn)
+	l += len(ret)
+
+	l += ULINT_SIZE
+
+	l += ULINT_SIZE
+
+	if strctDesc.m_objId == 4 {
+
+		l += ULINT_SIZE
+
+		l += ULINT_SIZE
+
+		l += USINT_SIZE
+	}
+
+	return l, nil
+}
+
+func packClass(strctDesc *TypeDescriptor, msg *Dm_build_361) error {
+
+	msg.Dm_build_416(strctDesc.column.colType)
+
+	msg.Dm_build_472(strctDesc.m_sqlName.m_name, strctDesc.getServerEncoding(), strctDesc.m_conn)
+
+	msg.Dm_build_416(int32(strctDesc.m_objId))
+
+	msg.Dm_build_416(int32(strctDesc.m_objVersion))
+
+	if strctDesc.m_objId == 4 {
+
+		msg.Dm_build_416(int32(strctDesc.m_outerId))
+
+		msg.Dm_build_416(int32(strctDesc.m_outerVer))
+
+		msg.Dm_build_416(int32(strctDesc.m_subId))
+
+	}
+
+	return nil
+}
+
+func (typeDescriptor *TypeDescriptor) unpack(buffer *Dm_build_361) error {
+
+	typeDescriptor.column.colType = buffer.Dm_build_490()
+
+	switch typeDescriptor.column.colType {
+	case ARRAY, SARRAY:
+		return typeDescriptor.unpackArray(buffer)
+	case CLASS:
+		return typeDescriptor.unpackClass(buffer)
+	case PLTYPE_RECORD:
+		return typeDescriptor.unpackRecord(buffer)
+	}
+
+	typeDescriptor.column.prec = buffer.Dm_build_490()
+
+	typeDescriptor.column.scale = buffer.Dm_build_490()
+	return nil
+}
+
+func (typeDescriptor *TypeDescriptor) unpackArray(buffer *Dm_build_361) error {
+
+	typeDescriptor.m_sqlName.m_name = buffer.Dm_build_540(typeDescriptor.getServerEncoding(), typeDescriptor.m_conn)
+
+	typeDescriptor.m_sqlName.m_schId = int(buffer.Dm_build_490())
+
+	typeDescriptor.m_sqlName.m_packId = int(buffer.Dm_build_490())
+
+	typeDescriptor.m_objId = int(buffer.Dm_build_490())
+
+	typeDescriptor.m_objVersion = int(buffer.Dm_build_490())
+
+	typeDescriptor.m_length = int(buffer.Dm_build_490())
+	if typeDescriptor.column.colType == ARRAY {
+		typeDescriptor.m_length = 0
+	}
+
+	typeDescriptor.m_arrObj = newTypeDescriptor(typeDescriptor.m_conn)
+	return typeDescriptor.m_arrObj.unpack(buffer)
+}
+
+func (typeDescriptor *TypeDescriptor) unpackRecord(buffer *Dm_build_361) error {
+
+	typeDescriptor.m_sqlName.m_name = buffer.Dm_build_540(typeDescriptor.getServerEncoding(), typeDescriptor.m_conn)
+
+	typeDescriptor.m_sqlName.m_schId = int(buffer.Dm_build_490())
+
+	typeDescriptor.m_sqlName.m_packId = int(buffer.Dm_build_490())
+
+	typeDescriptor.m_objId = int(buffer.Dm_build_490())
+
+	typeDescriptor.m_objVersion = int(buffer.Dm_build_490())
+
+	typeDescriptor.m_size = int(buffer.Dm_build_505())
+
+	typeDescriptor.m_fieldsObj = make([]TypeDescriptor, typeDescriptor.m_size)
+	for i := 0; i < typeDescriptor.m_size; i++ {
+		typeDescriptor.m_fieldsObj[i] = *newTypeDescriptor(typeDescriptor.m_conn)
+		typeDescriptor.m_fieldsObj[i].unpack(buffer)
+	}
+
+	return nil
+}
+
+func (typeDescriptor *TypeDescriptor) unpackClnt_nestTab(buffer *Dm_build_361) error {
+
+	typeDescriptor.m_maxCnt = int(buffer.Dm_build_490())
+
+	typeDescriptor.m_arrObj = newTypeDescriptor(typeDescriptor.m_conn)
+
+	typeDescriptor.m_arrObj.unpack(buffer)
+
+	return nil
+}
+
+func (typeDescriptor *TypeDescriptor) unpackClnt(buffer *Dm_build_361) error {
+
+	typeDescriptor.m_outerId = int(buffer.Dm_build_490())
+
+	typeDescriptor.m_outerVer = int(buffer.Dm_build_490())
+
+	typeDescriptor.m_subId = int(buffer.Dm_build_505())
+
+	typeDescriptor.m_cltnType = int(buffer.Dm_build_505())
+
+	switch typeDescriptor.m_cltnType {
+	case CLTN_TYPE_IND_TABLE:
+		return ECGO_UNSUPPORTED_TYPE.throw()
+
+	case CLTN_TYPE_NST_TABLE, CLTN_TYPE_VARRAY:
+		return typeDescriptor.unpackClnt_nestTab(buffer)
+
+	}
+	return nil
+}
+
+func (typeDescriptor *TypeDescriptor) unpackClass(buffer *Dm_build_361) error {
+
+	typeDescriptor.m_sqlName.m_name = buffer.Dm_build_540(typeDescriptor.getServerEncoding(), typeDescriptor.m_conn)
+
+	typeDescriptor.m_sqlName.m_schId = int(buffer.Dm_build_490())
+
+	typeDescriptor.m_sqlName.m_packId = int(buffer.Dm_build_490())
+
+	typeDescriptor.m_objId = int(buffer.Dm_build_490())
+
+	typeDescriptor.m_objVersion = int(buffer.Dm_build_490())
+
+	if typeDescriptor.m_objId == 4 {
+		return typeDescriptor.unpackClnt(buffer)
+	} else {
+
+		typeDescriptor.m_size = int(buffer.Dm_build_505())
+
+		typeDescriptor.m_fieldsObj = make([]TypeDescriptor, typeDescriptor.m_size)
+		for i := 0; i < typeDescriptor.m_size; i++ {
+			typeDescriptor.m_fieldsObj[i] = *newTypeDescriptor(typeDescriptor.m_conn)
+			err := typeDescriptor.m_fieldsObj[i].unpack(buffer)
+			if err != nil {
+				return err
+			}
+		}
+		return nil
+	}
+
+}
+
+func calcChkDescLen_array(desc *TypeDescriptor) (int, error) {
+	offset := 0
+
+	offset += USINT_SIZE
+
+	offset += ULINT_SIZE
+
+	tmp, err := calcChkDescLen(desc)
+	if err != nil {
+		return 0, err
+	}
+
+	offset += tmp
+
+	return offset, nil
+}
+
+func calcChkDescLen_record(desc *TypeDescriptor) (int, error) {
+	offset := 0
+
+	offset += USINT_SIZE
+
+	offset += USINT_SIZE
+
+	for i := 0; i < desc.m_size; i++ {
+		tmp, err := calcChkDescLen(&desc.m_fieldsObj[i])
+		if err != nil {
+			return 0, err
+		}
+		offset += tmp
+	}
+
+	return offset, nil
+}
+
+func calcChkDescLen_class_normal(desc *TypeDescriptor) (int, error) {
+	offset := 0
+
+	offset += USINT_SIZE
+
+	for i := 0; i < desc.m_size; i++ {
+		tmp, err := calcChkDescLen(&desc.m_fieldsObj[i])
+		if err != nil {
+			return 0, err
+		}
+		offset += tmp
+	}
+
+	return offset, nil
+}
+
+func calcChkDescLen_class_cnlt(desc *TypeDescriptor) (int, error) {
+	offset := 0
+
+	offset += USINT_SIZE
+
+	offset += ULINT_SIZE
+
+	switch desc.getCltnType() {
+	case CLTN_TYPE_IND_TABLE:
+		return 0, ECGO_UNSUPPORTED_TYPE.throw()
+
+	case CLTN_TYPE_VARRAY, CLTN_TYPE_NST_TABLE:
+
+		i, err := calcChkDescLen(desc.m_arrObj)
+		if err != nil {
+			return 0, err
+		}
+
+		offset += i
+	}
+
+	return offset, nil
+}
+
+func calcChkDescLen_class(desc *TypeDescriptor) (int, error) {
+	offset := 0
+
+	offset += USINT_SIZE
+
+	offset += BYTE_SIZE
+
+	if desc.m_objId == 4 {
+		i, err := calcChkDescLen_class_cnlt(desc)
+		if err != nil {
+			return 0, err
+		}
+		offset += i
+	} else {
+		i, err := calcChkDescLen_class_normal(desc)
+		if err != nil {
+			return 0, err
+		}
+		offset += i
+	}
+
+	return offset, nil
+}
+
+func calcChkDescLen_buildin() int {
+	offset := 0
+
+	offset += USINT_SIZE
+
+	offset += USINT_SIZE
+
+	offset += USINT_SIZE
+
+	return offset
+}
+
+func calcChkDescLen(desc *TypeDescriptor) (int, error) {
+
+	switch desc.getDType() {
+	case ARRAY, SARRAY:
+		return calcChkDescLen_array(desc)
+
+	case PLTYPE_RECORD:
+		return calcChkDescLen_record(desc)
+
+	case CLASS:
+		return calcChkDescLen_class(desc)
+
+	default:
+		return calcChkDescLen_buildin(), nil
+	}
+
+}
+
+func (typeDescriptor *TypeDescriptor) makeChkDesc_array(offset int, desc *TypeDescriptor) (int, error) {
+
+	Dm_build_1.Dm_build_12(typeDescriptor.m_descBuf, offset, ARRAY)
+	offset += USINT_SIZE
+
+	Dm_build_1.Dm_build_17(typeDescriptor.m_descBuf, offset, int32(desc.m_length))
+	offset += ULINT_SIZE
+
+	return typeDescriptor.makeChkDesc(offset, desc)
+}
+
+func (typeDescriptor *TypeDescriptor) makeChkDesc_record(offset int, desc *TypeDescriptor) (int, error) {
+
+	Dm_build_1.Dm_build_12(typeDescriptor.m_descBuf, offset, PLTYPE_RECORD)
+	offset += USINT_SIZE
+
+	Dm_build_1.Dm_build_12(typeDescriptor.m_descBuf, offset, int16(desc.m_size))
+	offset += USINT_SIZE
+	var err error
+	for i := 0; i < desc.m_size; i++ {
+		offset, err = typeDescriptor.makeChkDesc(offset, &desc.m_fieldsObj[i])
+		if err != nil {
+			return 0, err
+		}
+	}
+
+	return offset, nil
+}
+
+func (typeDescriptor *TypeDescriptor) makeChkDesc_buildin(offset int, desc *TypeDescriptor) int {
+	dtype := int16(desc.getDType())
+	prec := 0
+	scale := 0
+
+	if dtype != BLOB {
+		prec = desc.getPrec()
+		scale = desc.getScale()
+	}
+
+	Dm_build_1.Dm_build_12(typeDescriptor.m_descBuf, offset, dtype)
+	offset += USINT_SIZE
+
+	Dm_build_1.Dm_build_12(typeDescriptor.m_descBuf, offset, int16(prec))
+	offset += USINT_SIZE
+
+	Dm_build_1.Dm_build_12(typeDescriptor.m_descBuf, offset, int16(scale))
+	offset += USINT_SIZE
+
+	return offset
+}
+
+func (typeDescriptor *TypeDescriptor) makeChkDesc_class_normal(offset int, desc *TypeDescriptor) (int, error) {
+
+	Dm_build_1.Dm_build_12(typeDescriptor.m_descBuf, offset, int16(desc.m_size))
+	offset += USINT_SIZE
+	var err error
+
+	for i := 0; i < desc.m_size; i++ {
+		offset, err = typeDescriptor.makeChkDesc(offset, &desc.m_fieldsObj[i])
+		if err != nil {
+			return 0, err
+		}
+	}
+
+	return offset, nil
+}
+
+func (typeDescriptor *TypeDescriptor) makeChkDesc_class_clnt(offset int, desc *TypeDescriptor) (int, error) {
+
+	Dm_build_1.Dm_build_12(typeDescriptor.m_descBuf, offset, int16(desc.m_cltnType))
+	offset += USINT_SIZE
+
+	Dm_build_1.Dm_build_17(typeDescriptor.m_descBuf, offset, int32(desc.getMaxCnt()))
+	offset += ULINT_SIZE
+
+	switch desc.m_cltnType {
+	case CLTN_TYPE_IND_TABLE:
+		return 0, ECGO_UNSUPPORTED_TYPE.throw()
+
+	case CLTN_TYPE_NST_TABLE, CLTN_TYPE_VARRAY:
+
+		return typeDescriptor.makeChkDesc(offset, desc.m_arrObj)
+	}
+
+	return offset, nil
+}
+
+func (typeDescriptor *TypeDescriptor) makeChkDesc_class(offset int, desc *TypeDescriptor) (int, error) {
+
+	Dm_build_1.Dm_build_12(typeDescriptor.m_descBuf, offset, CLASS)
+	offset += USINT_SIZE
+
+	isClnt := false
+	if desc.m_objId == 4 {
+		isClnt = true
+	}
+
+	if isClnt {
+		Dm_build_1.Dm_build_2(typeDescriptor.m_descBuf, offset, byte(1))
+	} else {
+		Dm_build_1.Dm_build_2(typeDescriptor.m_descBuf, offset, byte(0))
+	}
+
+	offset += BYTE_SIZE
+
+	if isClnt {
+		return typeDescriptor.makeChkDesc_class_clnt(offset, desc)
+	} else {
+		return typeDescriptor.makeChkDesc_class_normal(offset, desc)
+	}
+}
+
+func (typeDescriptor *TypeDescriptor) makeChkDesc(offset int, subDesc *TypeDescriptor) (int, error) {
+	switch subDesc.getDType() {
+	case ARRAY, SARRAY:
+		return typeDescriptor.makeChkDesc_array(offset, subDesc)
+
+	case PLTYPE_RECORD:
+		return typeDescriptor.makeChkDesc_record(offset, subDesc)
+
+	case CLASS:
+		return typeDescriptor.makeChkDesc_class(offset, subDesc)
+
+	default:
+		return typeDescriptor.makeChkDesc_buildin(offset, subDesc), nil
+	}
+
+}
+
+func (typeDescriptor *TypeDescriptor) getClassDescChkInfo() ([]byte, error) {
+	if typeDescriptor.m_descBuf != nil {
+		return typeDescriptor.m_descBuf, nil
+	}
+
+	l, err := calcChkDescLen(typeDescriptor)
+	if err != nil {
+		return nil, err
+	}
+	typeDescriptor.m_descBuf = make([]byte, l)
+
+	typeDescriptor.makeChkDesc(0, typeDescriptor)
+	return typeDescriptor.m_descBuf, nil
+}