├── README.md ├── VERSION ├── a.go ├── b.go ├── c.go ├── connection.go ├── connector.go ├── d.go ├── e.go ├── endpoint.go ├── f.go ├── g.go ├── go.mod ├── go.sum ├── h.go ├── i.go ├── i18n ├── zj.go ├── zk.go ├── zl.go └── zm.go ├── j.go ├── k.go ├── l.go ├── main.go ├── o.go ├── parser ├── zt.go └── zu.go ├── q.go ├── r.go ├── s.go ├── security ├── zy.go ├── zz.go ├── zza.go ├── zzb.go ├── zzc.go ├── zzd.go ├── zze.go ├── zzf.go ├── zzg_linux.go ├── zzg_mac.go ├── zzh_windows.go └── zzi.go ├── t.go ├── u.go ├── util ├── zzq.go ├── zzr.go ├── zzs.go └── zzt.go ├── v.go ├── w.go ├── y.go ├── z.go ├── za.go ├── zb.go ├── zc.go ├── zd.go ├── ze.go ├── zf.go ├── zg.go ├── zh.go ├── zi.go ├── zn.go ├── zo.go ├── zp.go ├── zq.go ├── zr.go ├── zs.go ├── zv.go ├── zw.go ├── zx.go ├── zzj.go ├── zzk.go ├── zzl.go ├── zzm.go ├── zzn.go ├── zzo.go └── zzp.go /README.md: -------------------------------------------------------------------------------- 1 | # dm 2 | ### 介绍 3 | 达梦数据库是国产化的数据库,该类库是达梦数据的SDK 4 | 看到里面奇怪的文件名和函数名,不要喷,猜测是原版通过别的语言自动生成的吧。 5 | 6 | ### 特性 7 | Fork自`https://gitee.com/chunanyong/dm`,并做了一些优化 8 | * 去除全局配置 9 | * 优化命名方式 10 | * 增加mac方式编译 11 | 12 | ``` 13 | go get github.com/gotomicro/dmgo 14 | ``` 15 | 16 | ### 使用原生方式 17 | ```go 18 | package main 19 | 20 | import ( 21 | "database/sql" 22 | "fmt" 23 | 24 | _ "github.com/gotomicro/dmgo" 25 | ) 26 | 27 | func main() { 28 | obj, err := sql.Open("dm", "dm://username:password@ip:5236") 29 | if err != nil { 30 | panic(err) 31 | return 32 | } 33 | rows, err := obj.Query("select TABLE_NAME,comments TABLE_COMMENT from user_tab_comments") 34 | for rows.Next() { 35 | a := TableStruct{} 36 | rows.Scan(&a.TableName, &a.TableComment) 37 | fmt.Printf("a--------------->"+"%+v\n", a) 38 | } 39 | } 40 | 41 | type TableStruct struct { 42 | TableName string //表名 43 | TableComment string //表注释 44 | } 45 | ``` 46 | 47 | ### 使用gorm方式 48 | 49 | ### DSN 50 | dm://userName:password@ip:port 51 | 用户名(userName)就是数据库的名称,达梦用户模式和数据库名称是对应的 52 | 建议达梦使用UTF-8字符编码,不区分大小写 53 | 54 | ### 版本号 55 | golang三段位版本号和达梦四段位版本号不兼容,统一使用1.达梦主版本号.发布的小版本号,具体查看标签的备注 56 | 57 | * v1.8.0 备注是 达梦8.1.1.126 58 | * v1.8.1 备注是 达梦8.1.1.190 59 | * v1.8.2 备注是 达梦8.1.2.18 60 | * v1.8.4 备注是 达梦8.1.2.38 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | #8.1.2.38 2 | #2021.07.14 3 | #7050 4 | -------------------------------------------------------------------------------- /b.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package dm 7 | 8 | type ArrayDescriptor struct { 9 | m_typeDesc *TypeDescriptor 10 | } 11 | 12 | func newArrayDescriptor(fulName string, conn *Connection) (*ArrayDescriptor, error) { 13 | 14 | ad := new(ArrayDescriptor) 15 | 16 | if fulName == "" { 17 | return nil, ECGO_INVALID_COMPLEX_TYPE_NAME.throw() 18 | } 19 | 20 | ad.m_typeDesc = newTypeDescriptorWithFulName(fulName, conn) 21 | err := ad.m_typeDesc.parseDescByName() 22 | if err != nil { 23 | return nil, err 24 | } 25 | 26 | return ad, nil 27 | } 28 | 29 | func newArrayDescriptorByTypeDescriptor(desc *TypeDescriptor) *ArrayDescriptor { 30 | ad := new(ArrayDescriptor) 31 | ad.m_typeDesc = desc 32 | return ad 33 | } 34 | 35 | func (ad *ArrayDescriptor) getMDesc() *TypeDescriptor { 36 | return ad.m_typeDesc 37 | } 38 | 39 | func (ad *ArrayDescriptor) getItemDesc() *TypeDescriptor { 40 | return ad.m_typeDesc.m_arrObj 41 | } 42 | 43 | func (ad *ArrayDescriptor) getLength() int { 44 | return ad.m_typeDesc.m_length 45 | } 46 | -------------------------------------------------------------------------------- /d.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | package dm 6 | 7 | import ( 8 | "container/list" 9 | "io" 10 | ) 11 | 12 | type Dm_build_1498 struct { 13 | dm_build_1499 *list.List 14 | dm_build_1500 *dm_build_1552 15 | dm_build_1501 int 16 | } 17 | 18 | func Dm_build_1502() *Dm_build_1498 { 19 | return &Dm_build_1498{ 20 | dm_build_1499: list.New(), 21 | dm_build_1501: 0, 22 | } 23 | } 24 | 25 | func (dm_build_1504 *Dm_build_1498) Dm_build_1503() int { 26 | return dm_build_1504.dm_build_1501 27 | } 28 | 29 | func (dm_build_1506 *Dm_build_1498) Dm_build_1505(dm_build_1507 *Dm_build_0, dm_build_1508 int) int { 30 | var dm_build_1509 = 0 31 | var dm_build_1510 = 0 32 | for dm_build_1509 < dm_build_1508 && dm_build_1506.dm_build_1500 != nil { 33 | dm_build_1510 = dm_build_1506.dm_build_1500.dm_build_1560(dm_build_1507, dm_build_1508-dm_build_1509) 34 | if dm_build_1506.dm_build_1500.dm_build_1555 == 0 { 35 | dm_build_1506.dm_build_1542() 36 | } 37 | dm_build_1509 += dm_build_1510 38 | dm_build_1506.dm_build_1501 -= dm_build_1510 39 | } 40 | return dm_build_1509 41 | } 42 | 43 | func (dm_build_1512 *Dm_build_1498) Dm_build_1511(dm_build_1513 []byte, dm_build_1514 int, dm_build_1515 int) int { 44 | var dm_build_1516 = 0 45 | var dm_build_1517 = 0 46 | for dm_build_1516 < dm_build_1515 && dm_build_1512.dm_build_1500 != nil { 47 | dm_build_1517 = dm_build_1512.dm_build_1500.dm_build_1564(dm_build_1513, dm_build_1514, dm_build_1515-dm_build_1516) 48 | if dm_build_1512.dm_build_1500.dm_build_1555 == 0 { 49 | dm_build_1512.dm_build_1542() 50 | } 51 | dm_build_1516 += dm_build_1517 52 | dm_build_1512.dm_build_1501 -= dm_build_1517 53 | dm_build_1514 += dm_build_1517 54 | } 55 | return dm_build_1516 56 | } 57 | 58 | func (dm_build_1519 *Dm_build_1498) Dm_build_1518(dm_build_1520 io.Writer, dm_build_1521 int) int { 59 | var dm_build_1522 = 0 60 | var dm_build_1523 = 0 61 | for dm_build_1522 < dm_build_1521 && dm_build_1519.dm_build_1500 != nil { 62 | dm_build_1523 = dm_build_1519.dm_build_1500.dm_build_1569(dm_build_1520, dm_build_1521-dm_build_1522) 63 | if dm_build_1519.dm_build_1500.dm_build_1555 == 0 { 64 | dm_build_1519.dm_build_1542() 65 | } 66 | dm_build_1522 += dm_build_1523 67 | dm_build_1519.dm_build_1501 -= dm_build_1523 68 | } 69 | return dm_build_1522 70 | } 71 | 72 | func (dm_build_1525 *Dm_build_1498) Dm_build_1524(dm_build_1526 []byte, dm_build_1527 int, dm_build_1528 int) { 73 | if dm_build_1528 == 0 { 74 | return 75 | } 76 | var dm_build_1529 = dm_build_1556(dm_build_1526, dm_build_1527, dm_build_1528) 77 | if dm_build_1525.dm_build_1500 == nil { 78 | dm_build_1525.dm_build_1500 = dm_build_1529 79 | } else { 80 | dm_build_1525.dm_build_1499.PushBack(dm_build_1529) 81 | } 82 | dm_build_1525.dm_build_1501 += dm_build_1528 83 | } 84 | 85 | func (dm_build_1531 *Dm_build_1498) dm_build_1530(dm_build_1532 int) byte { 86 | var dm_build_1533 = dm_build_1532 87 | var dm_build_1534 = dm_build_1531.dm_build_1500 88 | for dm_build_1533 > 0 && dm_build_1534 != nil { 89 | if dm_build_1534.dm_build_1555 == 0 { 90 | continue 91 | } 92 | if dm_build_1533 > dm_build_1534.dm_build_1555-1 { 93 | dm_build_1533 -= dm_build_1534.dm_build_1555 94 | dm_build_1534 = dm_build_1531.dm_build_1499.Front().Value.(*dm_build_1552) 95 | } else { 96 | break 97 | } 98 | } 99 | return dm_build_1534.dm_build_1573(dm_build_1533) 100 | } 101 | func (dm_build_1536 *Dm_build_1498) Dm_build_1535(dm_build_1537 *Dm_build_1498) { 102 | if dm_build_1537.dm_build_1501 == 0 { 103 | return 104 | } 105 | var dm_build_1538 = dm_build_1537.dm_build_1500 106 | for dm_build_1538 != nil { 107 | dm_build_1536.dm_build_1539(dm_build_1538) 108 | dm_build_1537.dm_build_1542() 109 | dm_build_1538 = dm_build_1537.dm_build_1500 110 | } 111 | dm_build_1537.dm_build_1501 = 0 112 | } 113 | func (dm_build_1540 *Dm_build_1498) dm_build_1539(dm_build_1541 *dm_build_1552) { 114 | if dm_build_1541.dm_build_1555 == 0 { 115 | return 116 | } 117 | if dm_build_1540.dm_build_1500 == nil { 118 | dm_build_1540.dm_build_1500 = dm_build_1541 119 | } else { 120 | dm_build_1540.dm_build_1499.PushBack(dm_build_1541) 121 | } 122 | dm_build_1540.dm_build_1501 += dm_build_1541.dm_build_1555 123 | } 124 | 125 | func (dm_build_1543 *Dm_build_1498) dm_build_1542() { 126 | var dm_build_1544 = dm_build_1543.dm_build_1499.Front() 127 | if dm_build_1544 == nil { 128 | dm_build_1543.dm_build_1500 = nil 129 | } else { 130 | dm_build_1543.dm_build_1500 = dm_build_1544.Value.(*dm_build_1552) 131 | dm_build_1543.dm_build_1499.Remove(dm_build_1544) 132 | } 133 | } 134 | 135 | func (dm_build_1546 *Dm_build_1498) Dm_build_1545() []byte { 136 | var dm_build_1547 = make([]byte, dm_build_1546.dm_build_1501) 137 | var dm_build_1548 = dm_build_1546.dm_build_1500 138 | var dm_build_1549 = 0 139 | var dm_build_1550 = len(dm_build_1547) 140 | var dm_build_1551 = 0 141 | for dm_build_1548 != nil { 142 | if dm_build_1548.dm_build_1555 > 0 { 143 | if dm_build_1550 > dm_build_1548.dm_build_1555 { 144 | dm_build_1551 = dm_build_1548.dm_build_1555 145 | } else { 146 | dm_build_1551 = dm_build_1550 147 | } 148 | copy(dm_build_1547[dm_build_1549:dm_build_1549+dm_build_1551], dm_build_1548.dm_build_1553[dm_build_1548.dm_build_1554:dm_build_1548.dm_build_1554+dm_build_1551]) 149 | dm_build_1549 += dm_build_1551 150 | dm_build_1550 -= dm_build_1551 151 | } 152 | if dm_build_1546.dm_build_1499.Front() == nil { 153 | dm_build_1548 = nil 154 | } else { 155 | dm_build_1548 = dm_build_1546.dm_build_1499.Front().Value.(*dm_build_1552) 156 | } 157 | } 158 | return dm_build_1547 159 | } 160 | 161 | type dm_build_1552 struct { 162 | dm_build_1553 []byte 163 | dm_build_1554 int 164 | dm_build_1555 int 165 | } 166 | 167 | func dm_build_1556(dm_build_1557 []byte, dm_build_1558 int, dm_build_1559 int) *dm_build_1552 { 168 | return &dm_build_1552{ 169 | dm_build_1557, 170 | dm_build_1558, 171 | dm_build_1559, 172 | } 173 | } 174 | 175 | func (dm_build_1561 *dm_build_1552) dm_build_1560(dm_build_1562 *Dm_build_0, dm_build_1563 int) int { 176 | if dm_build_1561.dm_build_1555 <= dm_build_1563 { 177 | dm_build_1563 = dm_build_1561.dm_build_1555 178 | } 179 | dm_build_1562.Dm_build_79(dm_build_1561.dm_build_1553[dm_build_1561.dm_build_1554 : dm_build_1561.dm_build_1554+dm_build_1563]) 180 | dm_build_1561.dm_build_1554 += dm_build_1563 181 | dm_build_1561.dm_build_1555 -= dm_build_1563 182 | return dm_build_1563 183 | } 184 | 185 | func (dm_build_1565 *dm_build_1552) dm_build_1564(dm_build_1566 []byte, dm_build_1567 int, dm_build_1568 int) int { 186 | if dm_build_1565.dm_build_1555 <= dm_build_1568 { 187 | dm_build_1568 = dm_build_1565.dm_build_1555 188 | } 189 | copy(dm_build_1566[dm_build_1567:dm_build_1567+dm_build_1568], dm_build_1565.dm_build_1553[dm_build_1565.dm_build_1554:dm_build_1565.dm_build_1554+dm_build_1568]) 190 | dm_build_1565.dm_build_1554 += dm_build_1568 191 | dm_build_1565.dm_build_1555 -= dm_build_1568 192 | return dm_build_1568 193 | } 194 | 195 | func (dm_build_1570 *dm_build_1552) dm_build_1569(dm_build_1571 io.Writer, dm_build_1572 int) int { 196 | if dm_build_1570.dm_build_1555 <= dm_build_1572 { 197 | dm_build_1572 = dm_build_1570.dm_build_1555 198 | } 199 | dm_build_1571.Write(dm_build_1570.dm_build_1553[dm_build_1570.dm_build_1554 : dm_build_1570.dm_build_1554+dm_build_1572]) 200 | dm_build_1570.dm_build_1554 += dm_build_1572 201 | dm_build_1570.dm_build_1555 -= dm_build_1572 202 | return dm_build_1572 203 | } 204 | func (dm_build_1574 *dm_build_1552) dm_build_1573(dm_build_1575 int) byte { 205 | return dm_build_1574.dm_build_1553[dm_build_1574.dm_build_1554+dm_build_1575] 206 | } 207 | -------------------------------------------------------------------------------- /endpoint.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package dm 7 | 8 | import ( 9 | "context" 10 | "strconv" 11 | "strings" 12 | "sync" 13 | "time" 14 | ) 15 | 16 | const ( 17 | STATUS_VALID_TIME = 20 * time.Second // ms 18 | 19 | // sort 值 20 | SORT_SERVER_MODE_INVALID = -1 // 不允许连接的模式 21 | 22 | SORT_SERVER_NOT_ALIVE = -2 // 站点无法连接 23 | 24 | SORT_UNKNOWN = INT32_MAX // 站点还未连接过,模式未知 25 | 26 | SORT_NORMAL = 30 27 | 28 | SORT_PRIMARY = 20 29 | 30 | SORT_STANDBY = 10 31 | 32 | // OPEN>MOUNT>SUSPEND 33 | SORT_OPEN = 3 34 | 35 | SORT_MOUNT = 2 36 | 37 | SORT_SUSPEND = 1 38 | ) 39 | 40 | type ep struct { 41 | host string 42 | port int32 43 | alive bool 44 | statusRefreshTs int64 // 状态更新的时间点 45 | serverMode int32 46 | serverStatus int32 47 | dscControl bool 48 | sort int32 49 | epSeqno int32 50 | epStatus int32 51 | lock sync.Mutex 52 | } 53 | 54 | func newEP(host string, port int32) *ep { 55 | ep := new(ep) 56 | ep.host = host 57 | ep.port = port 58 | ep.serverMode = -1 59 | ep.serverStatus = -1 60 | ep.sort = SORT_UNKNOWN 61 | return ep 62 | } 63 | 64 | func (ep *ep) getSort(checkTime bool) int32 { 65 | if checkTime { 66 | if time.Now().UnixNano()-ep.statusRefreshTs < int64(STATUS_VALID_TIME) { 67 | return ep.sort 68 | } else { 69 | return SORT_UNKNOWN 70 | } 71 | } 72 | return ep.sort 73 | } 74 | 75 | func (ep *ep) calcSort(loginMode int32) int32 { 76 | var sort int32 = 0 77 | switch loginMode { 78 | case LOGIN_MODE_PRIMARY_FIRST: 79 | { 80 | // 主机优先:PRIMARY>NORMAL>STANDBY 81 | switch ep.serverMode { 82 | case SERVER_MODE_NORMAL: 83 | sort += SORT_NORMAL * 10 84 | case SERVER_MODE_PRIMARY: 85 | sort += SORT_PRIMARY * 100 86 | case SERVER_MODE_STANDBY: 87 | sort += SORT_STANDBY 88 | } 89 | } 90 | case LOGIN_MODE_STANDBY_FIRST: 91 | { 92 | // STANDBY优先: STANDBY>PRIMARY>NORMAL 93 | switch ep.serverMode { 94 | case SERVER_MODE_NORMAL: 95 | sort += SORT_NORMAL 96 | case SERVER_MODE_PRIMARY: 97 | sort += SORT_PRIMARY * 10 98 | case SERVER_MODE_STANDBY: 99 | sort += SORT_STANDBY * 100 100 | } 101 | } 102 | case LOGIN_MODE_PRIMARY_ONLY: 103 | if ep.serverMode != SERVER_MODE_PRIMARY { 104 | return SORT_SERVER_MODE_INVALID 105 | } 106 | sort += SORT_PRIMARY 107 | case LOGIN_MODE_STANDBY_ONLY: 108 | if ep.serverMode != SERVER_MODE_STANDBY { 109 | return SORT_SERVER_MODE_INVALID 110 | } 111 | sort += SORT_STANDBY 112 | } 113 | 114 | switch ep.serverStatus { 115 | case SERVER_STATUS_MOUNT: 116 | sort += SORT_MOUNT 117 | case SERVER_STATUS_OPEN: 118 | sort += SORT_OPEN 119 | case SERVER_STATUS_SUSPEND: 120 | sort += SORT_SUSPEND 121 | } 122 | return sort 123 | } 124 | 125 | func (ep *ep) refreshStatus(alive bool, conn *Connection) { 126 | ep.lock.Lock() 127 | defer ep.lock.Unlock() 128 | ep.alive = alive 129 | ep.statusRefreshTs = time.Now().UnixNano() 130 | if alive { 131 | ep.serverMode = conn.SvrMode 132 | ep.serverStatus = conn.SvrStat 133 | ep.dscControl = conn.dscControl 134 | ep.sort = ep.calcSort(int32(conn.dmConnector.loginMode)) 135 | } else { 136 | ep.serverMode = -1 137 | ep.serverStatus = -1 138 | ep.dscControl = false 139 | ep.sort = SORT_SERVER_NOT_ALIVE 140 | } 141 | } 142 | 143 | func (ep *ep) connect(connector *Connector) (*Connection, error) { 144 | connector.host = ep.host 145 | connector.port = ep.port 146 | conn, err := connector.connectSingle(context.Background()) 147 | if err != nil { 148 | ep.refreshStatus(false, conn) 149 | return nil, err 150 | } 151 | ep.refreshStatus(true, conn) 152 | return conn, nil 153 | } 154 | 155 | func (ep *ep) getServerStatusDesc(serverStatus int32) string { 156 | ret := "" 157 | switch ep.serverStatus { 158 | case SERVER_STATUS_OPEN: 159 | ret = "OPEN" 160 | case SERVER_STATUS_MOUNT: 161 | ret = "MOUNT" 162 | case SERVER_STATUS_SUSPEND: 163 | ret = "SUSPEND" 164 | default: 165 | ret = "UNKNOWN" 166 | } 167 | return ret 168 | } 169 | 170 | func (ep *ep) getServerModeDesc(serverMode int32) string { 171 | ret := "" 172 | switch ep.serverMode { 173 | case SERVER_MODE_NORMAL: 174 | ret = "NORMAL" 175 | case SERVER_MODE_PRIMARY: 176 | ret = "PRIMARY" 177 | case SERVER_MODE_STANDBY: 178 | ret = "STANDBY" 179 | default: 180 | ret = "UNKNOWN" 181 | } 182 | return ret 183 | } 184 | 185 | func (ep *ep) String() string { 186 | dscControl := ")" 187 | if ep.dscControl { 188 | dscControl = ", DSC CONTROL)" 189 | } 190 | return strings.TrimSpace(ep.host) + ":" + strconv.Itoa(int(ep.port)) + 191 | " (" + ep.getServerModeDesc(ep.serverMode) + ", " + ep.getServerStatusDesc(ep.serverStatus) + dscControl 192 | } 193 | -------------------------------------------------------------------------------- /f.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | package dm 6 | 7 | import ( 8 | "bytes" 9 | "compress/zlib" 10 | "github.com/golang/snappy" 11 | ) 12 | 13 | func Compress(srcBuffer *Dm_build_0, offset int, length int, compressID int) ([]byte, error) { 14 | if compressID == Dm_build_682 { 15 | return snappy.Encode(nil, srcBuffer.Dm_build_290(offset, length)), nil 16 | } 17 | return GzlibCompress(srcBuffer, offset, length) 18 | } 19 | 20 | func UnCompress(srcBytes []byte, compressID int) ([]byte, error) { 21 | if compressID == Dm_build_682 { 22 | return snappy.Decode(nil, srcBytes) 23 | } 24 | return GzlibUncompress(srcBytes) 25 | } 26 | 27 | func GzlibCompress(srcBuffer *Dm_build_0, offset int, length int) ([]byte, error) { 28 | var ret bytes.Buffer 29 | var w = zlib.NewWriter(&ret) 30 | w.Write(srcBuffer.Dm_build_290(offset, length)) 31 | w.Close() 32 | return ret.Bytes(), nil 33 | } 34 | 35 | func GzlibUncompress(srcBytes []byte) ([]byte, error) { 36 | var bytesBuf = new(bytes.Buffer) 37 | r, err := zlib.NewReader(bytes.NewReader(srcBytes)) 38 | if err != nil { 39 | return nil, err 40 | } 41 | defer r.Close() 42 | _, err = bytesBuf.ReadFrom(r) 43 | if err != nil { 44 | return nil, err 45 | } 46 | return bytesBuf.Bytes(), nil 47 | } 48 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gotomicro/dmgo 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/golang/snappy v0.0.1 7 | golang.org/x/text v0.3.2 8 | ) 9 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= 2 | github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 3 | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= 4 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 5 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 6 | -------------------------------------------------------------------------------- /i18n/zj.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package i18n 7 | 8 | import ( 9 | "encoding/json" 10 | "golang.org/x/text/language" 11 | "golang.org/x/text/message" 12 | ) 13 | 14 | type msg struct { 15 | Id string `json:"id"` 16 | Translation string `json:"translation,omitempty"` 17 | } 18 | 19 | type i18n struct { 20 | Language string `json:"language"` 21 | Messages []msg `json:"messages"` 22 | } 23 | 24 | func InitConfig(jsonStr string) { 25 | 26 | var i18n i18n 27 | json.Unmarshal([]byte(jsonStr), &i18n) 28 | msaArry := i18n.Messages 29 | tag := language.MustParse(i18n.Language) 30 | for _, e := range msaArry { 31 | message.SetString(tag, e.Id, e.Translation) 32 | } 33 | } 34 | 35 | func Get(key string, locale int) string { 36 | var p *message.Printer 37 | 38 | switch locale { 39 | case 0: 40 | p = message.NewPrinter(language.SimplifiedChinese) 41 | case 1: 42 | p = message.NewPrinter(language.AmericanEnglish) 43 | case 2: 44 | p = message.NewPrinter(language.TraditionalChinese) 45 | } 46 | 47 | return p.Sprintf(key) 48 | } 49 | -------------------------------------------------------------------------------- /i18n/zk.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package i18n 7 | 8 | const Messages_en_US = `{ 9 | "language": "en-US", 10 | "messages": [ 11 | { 12 | "id": "error.dsn.invalidSchema", 13 | "translation": "DSN must start with dm://" 14 | }, 15 | { 16 | "id": "error.unsupported.scan", 17 | "translation": "Unsupported scan type" 18 | }, 19 | { 20 | "id": "error.invalidParameterNumber", 21 | "translation": "Invalid parameter number" 22 | }, 23 | { 24 | "id": "error.initThirdPartCipherFailed", 25 | "translation": "Init third part cipher failed" 26 | }, 27 | { 28 | "id": "error.connectionSwitchFailed", 29 | "translation": "Connection switch failed" 30 | }, 31 | { 32 | "id": "error.connectionSwitched", 33 | "translation": "Connection has been switched" 34 | }, 35 | { 36 | "id": "error.invalidServerMode", 37 | "translation": "Invalid server mode" 38 | }, 39 | { 40 | "id": "error.osauthError", 41 | "translation": "At the same time using the specifed user login and OS authentication login, please determine a way." 42 | }, 43 | { 44 | "id": "error.notQuerySQL", 45 | "translation": "The SQL is not a query SQL" 46 | }, 47 | { 48 | "id": "error.notExecSQL", 49 | "translation": "The SQL is not a execute SQL" 50 | }, 51 | { 52 | "id": "error.invalidTranIsolation", 53 | "translation": "invalid Transaltion Isolation" 54 | }, 55 | { 56 | "id": "errorCommitInAutoCommitMode", 57 | "translation": "Can't commit in Auto commit status" 58 | }, 59 | { 60 | "id": "errorCommitInAutoCommitMode", 61 | "translation": "Can't rollback in Auto commit status" 62 | }, 63 | { 64 | "id": "errorStatementHandleClosed", 65 | "translation": "Statement handle is closed" 66 | }, 67 | { 68 | "id": "errorResultSetColsed", 69 | "translation": "Resultset is closed" 70 | }, 71 | { 72 | "id": "error.communicationError", 73 | "translation": "Communication error" 74 | }, 75 | { 76 | "id": "error.msgCheckError", 77 | "translation": "Message check error" 78 | }, 79 | { 80 | "id": "error.unkownNetWork", 81 | "translation": "Unkown net work" 82 | }, 83 | { 84 | "id": "error.serverVersion", 85 | "translation": "Server version is too low" 86 | }, 87 | { 88 | "id": "error.usernameTooLong", 89 | "translation": "Username is too long." 90 | }, 91 | { 92 | "id": "error.passwordTooLong", 93 | "translation": "Password to login is too long." 94 | }, 95 | { 96 | "id": "error.dataTooLong", 97 | "translation": "The data is too large to support." 98 | }, 99 | { 100 | "id": "error.invalidColumnType", 101 | "translation": "Invalid column type" 102 | }, 103 | { 104 | "id": "error.dataConvertionError", 105 | "translation": "Data convertion error" 106 | }, 107 | { 108 | "id": "error.invalidConn", 109 | "translation": "Invalid connection" 110 | }, 111 | { 112 | "id": "error.invalidHex", 113 | "translation": "Invalid Hex Number." 114 | }, 115 | { 116 | "id": "error.invalidBFile", 117 | "translation": "Invalid BFile format string." 118 | }, 119 | { 120 | "id": "error.dataOverflow", 121 | "translation": "Digital overflow" 122 | }, 123 | { 124 | "id": "error.invalidDateTimeFormat", 125 | "translation": "Invalid datetime type format" 126 | }, 127 | { 128 | "id": "error.datetimeOverflow", 129 | "translation": "Digital overflow" 130 | }, 131 | { 132 | "id": "error.invalidTimeInterval", 133 | "translation": "Invalid time interval type value" 134 | }, 135 | { 136 | "id": "error.unsupportedInparamType", 137 | "translation": "Unsupported input parameter type" 138 | }, 139 | { 140 | "id": "error.unsupportedOutparamType", 141 | "translation": "Unsupported output parameter type" 142 | }, 143 | { 144 | "id": "error.unsupportedType", 145 | "translation": "Not support this type" 146 | }, 147 | { 148 | "id": "error.invalidObjBlob", 149 | "translation": "invalid Object Blob Data." 150 | }, 151 | { 152 | "id": "error.structMemNotMatch", 153 | "translation": "Members are not matched in Record or Class" 154 | }, 155 | { 156 | "id": "error.invalidComplexTypeName", 157 | "translation": "Invalid descriptor name." 158 | }, 159 | { 160 | "id": "error.invalidParamterValue", 161 | "translation": "Invalid parameter value" 162 | }, 163 | { 164 | "id": "error.invalidArrayLen", 165 | "translation": "the length of static array is bigger than the one when defined." 166 | }, 167 | { 168 | "id": "error.invalidSequenceNumber", 169 | "translation": "Invalid sequence no" 170 | }, 171 | { 172 | "id": "error.resultsetInReadOnlyStatus", 173 | "translation": "Resultset in readonly status" 174 | }, 175 | { 176 | "id": "error.SSLInitFailed", 177 | "translation": "Failed to initialize SSL" 178 | }, 179 | { 180 | "id": "error.LobDataHasFreed", 181 | "translation": "Lob Data has been freed" 182 | }, 183 | { 184 | "id": "error.fatalError", 185 | "translation": "Fatal error" 186 | }, 187 | { 188 | "id": "error.invalidLenOrOffset", 189 | "translation": "Invalid length or offset" 190 | }, 191 | { 192 | "id": "error.intervalValueOverflow", 193 | "translation": "interval type value overflow" 194 | }, 195 | { 196 | "id": "error.invalidCipher", 197 | "translation": "Invalid cipher type" 198 | }, 199 | { 200 | "id": "error.storeInNilPointer", 201 | "translation": "Can't store value into a nil pointer" 202 | }, 203 | { 204 | "id": "error.batchError", 205 | "translation": "Error in executing with batch" 206 | }, 207 | { 208 | "id": "warning.bpWithErr", 209 | "translation": "Warning:Partial failure on execute with batch" 210 | }, 211 | { 212 | "id": "error.invalidSqlType", 213 | "translation": "Invalid sql type" 214 | }, 215 | { 216 | "id": "error.invalidDateTimeValue", 217 | "translation": "Invalid datetime value" 218 | } 219 | ] 220 | }` -------------------------------------------------------------------------------- /i18n/zl.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package i18n 7 | 8 | const Messages_zh_CN = `{ 9 | "language": "zh-Hans", 10 | "messages": [ 11 | { 12 | "id": "error.dsn.invalidSchema", 13 | "translation": "DSN串必须以dm://开头" 14 | }, 15 | { 16 | "id": "error.unsupported.scan", 17 | "translation": "Scan类型转换出错" 18 | }, 19 | { 20 | "id": "error.invalidParameterNumber", 21 | "translation": "参数个数不匹配" 22 | }, 23 | { 24 | "id": "error.initThirdPartCipherFailed", 25 | "translation": "第三方加密初始化失败" 26 | }, 27 | { 28 | "id": "error.connectionSwitchFailed", 29 | "translation": "连接重置失败" 30 | }, 31 | { 32 | "id": "error.connectionSwitched", 33 | "translation": "连接已重置" 34 | }, 35 | { 36 | "id": "error.invalidServerMode", 37 | "translation": "服务器模式不匹配" 38 | }, 39 | { 40 | "id": "error.osauthError", 41 | "translation": "同时使用了指定用户登录和OS认证登录, 请确定一种方式." 42 | }, 43 | { 44 | "id": "error.notQuerySQL", 45 | "translation": "非查询SQL语句" 46 | }, 47 | { 48 | "id": "error.notExecSQL", 49 | "translation": "非执行SQL语句" 50 | }, 51 | { 52 | "id": "error.invalidTranIsolation", 53 | "translation": "非法的事务隔离级" 54 | }, 55 | { 56 | "id": "errorCommitInAutoCommitMode", 57 | "translation": "自动提交模式下不能手动提交" 58 | }, 59 | { 60 | "id": "errorRollbackInAutoCommitMode", 61 | "translation": "自动提交模式下不能手动回滚" 62 | }, 63 | { 64 | "id": "errorStatementHandleClosed", 65 | "translation": "语句已经关闭" 66 | }, 67 | { 68 | "id": "errorResultSetColsed", 69 | "translation": "结果集已经关闭" 70 | }, 71 | { 72 | "id": "error.communicationError", 73 | "translation": "网络通信异常" 74 | }, 75 | { 76 | "id": "error.msgCheckError", 77 | "translation": "消息校验异常" 78 | }, 79 | { 80 | "id": "error.unkownNetWork", 81 | "translation": "未知的网络" 82 | }, 83 | { 84 | "id": "error.serverVersion", 85 | "translation": "服务器版本太低" 86 | }, 87 | { 88 | "id": "error.usernameTooLong", 89 | "translation": "用户名超长" 90 | }, 91 | { 92 | "id": "error.passwordTooLong", 93 | "translation": "密码超长" 94 | }, 95 | { 96 | "id": "error.dataTooLong", 97 | "translation": "数据大小已超过可支持范围" 98 | }, 99 | { 100 | "id": "error.invalidColumnType", 101 | "translation": "无效的列类型" 102 | }, 103 | { 104 | "id": "error.dataConvertionError", 105 | "translation": "类型转换异常" 106 | }, 107 | { 108 | "id": "error.invalidConn", 109 | "translation": "连接失效" 110 | }, 111 | { 112 | "id": "error.invalidHex", 113 | "translation": "无效的十六进制数字" 114 | }, 115 | { 116 | "id": "error.invalidBFile", 117 | "translation": "无效的BFile格式串" 118 | }, 119 | { 120 | "id": "error.dataOverflow", 121 | "translation": "数字溢出" 122 | }, 123 | { 124 | "id": "error.invalidDateTimeFormat", 125 | "translation": "错误的日期时间类型格式" 126 | }, 127 | { 128 | "id": "error.datetimeOverflow", 129 | "translation": "数字溢出" 130 | }, 131 | { 132 | "id": "error.invalidTimeInterval", 133 | "translation": "错误的时间间隔类型数据" 134 | }, 135 | { 136 | "id": "error.unsupportedInparamType", 137 | "translation": "输入参数类型不支持" 138 | }, 139 | { 140 | "id": "error.unsupportedOutparamType", 141 | "translation": "输出参数类型不支持" 142 | }, 143 | { 144 | "id": "error.unsupportedType", 145 | "translation": "不支持该数据类型" 146 | }, 147 | { 148 | "id": "error.invalidObjBlob", 149 | "translation": "无效的对象BLOB数据" 150 | }, 151 | { 152 | "id": "error.structMemNotMatch", 153 | "translation": "记录或类数据成员不匹配" 154 | }, 155 | { 156 | "id": "error.invalidComplexTypeName", 157 | "translation": "无效的类型描述名称" 158 | }, 159 | { 160 | "id": "error.invalidParamterValue", 161 | "translation": "无效的参数值" 162 | }, 163 | { 164 | "id": "error.invalidArrayLen", 165 | "translation": "静态数组长度大于定义时长度" 166 | }, 167 | { 168 | "id": "error.invalidSequenceNumber", 169 | "translation": "无效的列序号" 170 | }, 171 | { 172 | "id": "error.resultsetInReadOnlyStatus", 173 | "translation": "结果集处于只读状态" 174 | }, 175 | { 176 | "id": "error.SSLInitFailed", 177 | "translation": "初始化SSL环境失败" 178 | }, 179 | { 180 | "id": "error.LobDataHasFreed", 181 | "translation": "LOB数据已经被释放" 182 | }, 183 | { 184 | "id": "error.fatalError", 185 | "translation": "致命错误" 186 | }, 187 | { 188 | "id": "error.invalidLenOrOffset", 189 | "translation": "长度或偏移错误" 190 | }, 191 | { 192 | "id": "error.intervalValueOverflow", 193 | "translation": "时间间隔类型数据溢出" 194 | }, 195 | { 196 | "id": "error.invalidCipher", 197 | "translation": "不支持的加密类型" 198 | }, 199 | { 200 | "id": "error.storeInNilPointer", 201 | "translation": "无法将数据存入空指针" 202 | }, 203 | { 204 | "id": "error.batchError", 205 | "translation": "批量执行出错" 206 | }, 207 | { 208 | "id": "warning.bpWithErr", 209 | "translation": "警告:批量执行部分行产生错误" 210 | }, 211 | { 212 | "id": "error.invalidSqlType", 213 | "translation": "非法的SQL语句类型" 214 | }, 215 | { 216 | "id": "error.invalidDateTimeValue", 217 | "translation": "无效的日期时间类型值" 218 | } 219 | ] 220 | }` -------------------------------------------------------------------------------- /i18n/zm.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package i18n 7 | 8 | const Messages_zh_TW = `{ 9 | "language": "zh-Hant", 10 | "messages": [ 11 | { 12 | "id": "error.dsn.invalidSchema", 13 | "translation": "DSN串必須以dm://開頭" 14 | }, 15 | { 16 | "id": "error.communicationError", 17 | "translation": "網絡通信異常" 18 | }, 19 | { 20 | "id": "error.msgCheckError", 21 | "translation": "消息校驗異常" 22 | }, 23 | { 24 | "id": "error.unkownNetWork", 25 | "translation": "未知的網絡" 26 | } 27 | ] 28 | }` -------------------------------------------------------------------------------- /j.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package dm 7 | 8 | type DmArray struct { 9 | TypeData 10 | m_arrDesc *ArrayDescriptor // 数组的描述信息 11 | 12 | m_arrData []TypeData // 数组中各行数据值 13 | 14 | m_objArray interface{} // 从服务端获取的 15 | 16 | m_itemCount int // 本次获取的行数 17 | 18 | m_itemSize int // 数组中一个数组项的大小,单位bytes 19 | 20 | m_objCount int // 一个数组项中存在对象类型的个数(class、动态数组) 21 | 22 | m_strCount int // 一个数组项中存在字符串类型的个数 23 | 24 | m_objStrOffs []int // 对象在前,字符串在后 25 | 26 | typeName string 27 | 28 | elements []interface{} 29 | } 30 | 31 | func (da *DmArray) init() *DmArray { 32 | da.initTypeData() 33 | da.m_itemCount = 0 34 | da.m_itemSize = 0 35 | da.m_objCount = 0 36 | da.m_strCount = 0 37 | da.m_objStrOffs = nil 38 | da.m_dumyData = nil 39 | da.m_offset = 0 40 | 41 | da.m_objArray = nil 42 | return da 43 | } 44 | 45 | func NewDmArray(typeName string, elements []interface{}) *DmArray { 46 | da := new(DmArray) 47 | da.typeName = typeName 48 | da.elements = elements 49 | return da 50 | } 51 | 52 | func (da *DmArray) create(dc *Connection) (*DmArray, error) { 53 | desc, err := newArrayDescriptor(da.typeName, dc) 54 | if err != nil { 55 | return nil, err 56 | } 57 | return da.createByArrayDescriptor(desc, dc) 58 | } 59 | 60 | func (da *DmArray) createByArrayDescriptor(arrDesc *ArrayDescriptor, conn *Connection) (*DmArray, error) { 61 | 62 | if nil == arrDesc { 63 | return nil, ECGO_INVALID_PARAMETER_VALUE.throw() 64 | } 65 | 66 | da.init() 67 | 68 | da.m_arrDesc = arrDesc 69 | if nil == da.elements { 70 | da.m_arrData = make([]TypeData, 0) 71 | } else { 72 | // 若为静态数组,判断给定数组长度是否超过静态数组的上限 73 | if arrDesc.getMDesc() == nil || (arrDesc.getMDesc().getDType() == SARRAY && len(da.elements) > arrDesc.getMDesc().getStaticArrayLength()) { 74 | return nil, ECGO_INVALID_ARRAY_LEN.throw() 75 | } 76 | 77 | var err error 78 | da.m_arrData, err = TypeDataSV.toArray(da.elements, da.m_arrDesc.getMDesc()) 79 | if err != nil { 80 | return nil, err 81 | } 82 | } 83 | 84 | da.m_itemCount = len(da.m_arrData) 85 | return da, nil 86 | } 87 | 88 | func newDmArrayByTypeData(atData []TypeData, desc *TypeDescriptor) *DmArray { 89 | da := new(DmArray) 90 | da.init() 91 | da.m_arrDesc = newArrayDescriptorByTypeDescriptor(desc) 92 | da.m_arrData = atData 93 | return da 94 | } 95 | 96 | func (da *DmArray) checkIndex(index int64) error { 97 | if index < 1 || index > int64(len(da.m_arrData)) { 98 | return ECGO_INVALID_LENGTH_OR_OFFSET.throw() 99 | } 100 | return nil 101 | } 102 | 103 | func (da *DmArray) checkIndexAndCount(index int64, count int) error { 104 | err := da.checkIndex(index) 105 | if err != nil { 106 | return err 107 | } 108 | 109 | if count <= 0 || index-int64(1)+int64(count) > int64(len(da.m_arrData)) { 110 | return ECGO_INVALID_LENGTH_OR_OFFSET.throw() 111 | } 112 | return nil 113 | } 114 | 115 | func (da *DmArray) GetBaseTypeName() (string, error) { 116 | return da.m_arrDesc.m_typeDesc.getFulName() 117 | } 118 | 119 | func (da *DmArray) GetObjArray(index int64, count int) (interface{}, error) { 120 | da.checkIndexAndCount(index, count) 121 | 122 | return TypeDataSV.toJavaArray(da, index, count, da.m_arrDesc.getItemDesc().getDType()) 123 | } 124 | 125 | func (da *DmArray) GetIntArray(index int64, count int) ([]int, error) { 126 | da.checkIndexAndCount(index, count) 127 | tmp, err := TypeDataSV.toNumericArray(da, index, count, ARRAY_TYPE_INTEGER) 128 | if err != nil { 129 | return nil, err 130 | } 131 | return tmp.([]int), nil 132 | } 133 | 134 | func (da *DmArray) GetInt16Array(index int64, count int) ([]int16, error) { 135 | da.checkIndexAndCount(index, count) 136 | 137 | tmp, err := TypeDataSV.toNumericArray(da, index, count, ARRAY_TYPE_SHORT) 138 | if err != nil { 139 | return nil, err 140 | } 141 | return tmp.([]int16), nil 142 | } 143 | 144 | func (da *DmArray) GetInt64Array(index int64, count int) ([]int64, error) { 145 | da.checkIndexAndCount(index, count) 146 | 147 | tmp, err := TypeDataSV.toNumericArray(da, index, count, ARRAY_TYPE_LONG) 148 | if err != nil { 149 | return nil, err 150 | } 151 | 152 | return tmp.([]int64), nil 153 | } 154 | 155 | func (da *DmArray) GetFloatArray(index int64, count int) ([]float32, error) { 156 | da.checkIndexAndCount(index, count) 157 | 158 | tmp, err := TypeDataSV.toNumericArray(da, index, count, ARRAY_TYPE_FLOAT) 159 | if err != nil { 160 | return nil, err 161 | } 162 | 163 | return tmp.([]float32), nil 164 | } 165 | 166 | func (da *DmArray) GetDoubleArray(index int64, count int) ([]float64, error) { 167 | da.checkIndexAndCount(index, count) 168 | 169 | tmp, err := TypeDataSV.toNumericArray(da, index, count, ARRAY_TYPE_DOUBLE) 170 | if err != nil { 171 | return nil, err 172 | } 173 | 174 | return tmp.([]float64), nil 175 | } 176 | 177 | func (dest *DmArray) Scan(src interface{}) error { 178 | if dest == nil { 179 | return ECGO_STORE_IN_NIL_POINTER.throw() 180 | } 181 | switch src := src.(type) { 182 | case nil: 183 | *dest = *new(DmArray) 184 | return nil 185 | case *DmArray: 186 | *dest = *src 187 | return nil 188 | default: 189 | return UNSUPPORTED_SCAN 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /k.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | package dm 6 | 7 | import ( 8 | "io" 9 | ) 10 | 11 | type DmBlob struct { 12 | lob 13 | data []byte 14 | offset int64 15 | } 16 | 17 | func newDmBlob() *DmBlob { 18 | return &DmBlob{ 19 | lob: lob{ 20 | inRow: true, 21 | groupId: -1, 22 | fileId: -1, 23 | pageNo: -1, 24 | readOver: false, 25 | local: true, 26 | updateable: true, 27 | length: -1, 28 | compatibleOracle: false, 29 | fetchAll: false, 30 | freed: false, 31 | modify: false, 32 | }, 33 | offset: 1, 34 | } 35 | } 36 | 37 | func newBlobFromDB(value []byte, conn *Connection, column *column, fetchAll bool) *DmBlob { 38 | var blob = newDmBlob() 39 | blob.connection = conn 40 | blob.lobFlag = LOB_FLAG_BYTE 41 | blob.compatibleOracle = conn.CompatibleOracle() 42 | blob.local = false 43 | blob.updateable = !column.readonly 44 | blob.tabId = column.lobTabId 45 | blob.colId = column.lobColId 46 | 47 | blob.inRow = Dm_build_1219.Dm_build_1312(value, NBLOB_HEAD_IN_ROW_FLAG) == LOB_IN_ROW 48 | blob.blobId = Dm_build_1219.Dm_build_1326(value, NBLOB_HEAD_BLOBID) 49 | if !blob.inRow { 50 | blob.groupId = Dm_build_1219.Dm_build_1316(value, NBLOB_HEAD_OUTROW_GROUPID) 51 | blob.fileId = Dm_build_1219.Dm_build_1316(value, NBLOB_HEAD_OUTROW_FILEID) 52 | blob.pageNo = Dm_build_1219.Dm_build_1321(value, NBLOB_HEAD_OUTROW_PAGENO) 53 | } 54 | if conn.NewLobFlag { 55 | blob.tabId = Dm_build_1219.Dm_build_1321(value, NBLOB_EX_HEAD_TABLE_ID) 56 | blob.colId = Dm_build_1219.Dm_build_1316(value, NBLOB_EX_HEAD_COL_ID) 57 | blob.rowId = Dm_build_1219.Dm_build_1326(value, NBLOB_EX_HEAD_ROW_ID) 58 | blob.exGroupId = Dm_build_1219.Dm_build_1316(value, NBLOB_EX_HEAD_FPA_GRPID) 59 | blob.exFileId = Dm_build_1219.Dm_build_1316(value, NBLOB_EX_HEAD_FPA_FILEID) 60 | blob.exPageNo = Dm_build_1219.Dm_build_1321(value, NBLOB_EX_HEAD_FPA_PAGENO) 61 | } 62 | blob.resetCurrentInfo() 63 | 64 | blob.length = blob.getLengthFromHead(value) 65 | if blob.inRow { 66 | blob.data = make([]byte, blob.length) 67 | if conn.NewLobFlag { 68 | Dm_build_1219.Dm_build_1275(blob.data, 0, value, NBLOB_EX_HEAD_SIZE, len(blob.data)) 69 | } else { 70 | Dm_build_1219.Dm_build_1275(blob.data, 0, value, NBLOB_INROW_HEAD_SIZE, len(blob.data)) 71 | } 72 | } else if fetchAll { 73 | blob.loadAllData() 74 | } 75 | return blob 76 | } 77 | 78 | func newBlobOfLocal(value []byte, conn *Connection) *DmBlob { 79 | var blob = newDmBlob() 80 | blob.connection = conn 81 | blob.lobFlag = LOB_FLAG_BYTE 82 | blob.data = value 83 | blob.length = int64(len(blob.data)) 84 | return blob 85 | } 86 | 87 | func NewBlob(value []byte) *DmBlob { 88 | var blob = newDmBlob() 89 | 90 | blob.lobFlag = LOB_FLAG_BYTE 91 | blob.data = value 92 | blob.length = int64(len(blob.data)) 93 | return blob 94 | } 95 | 96 | func (blob *DmBlob) Read(dest []byte) (n int, err error) { 97 | result, err := blob.getBytes(blob.offset, int32(len(dest))) 98 | if err != nil { 99 | return 0, err 100 | } 101 | blob.offset += int64(len(result)) 102 | copy(dest, result) 103 | if len(result) == 0 { 104 | return 0, io.EOF 105 | } 106 | return len(result), nil 107 | } 108 | 109 | func (blob *DmBlob) ReadAt(pos int, dest []byte) (n int, err error) { 110 | result, err := blob.getBytes(int64(pos), int32(len(dest))) 111 | if err != nil { 112 | return 0, err 113 | } 114 | if len(result) == 0 { 115 | return 0, io.EOF 116 | } 117 | copy(dest[0:len(result)], result) 118 | return len(result), nil 119 | } 120 | 121 | func (blob *DmBlob) Write(pos int, src []byte) (n int, err error) { 122 | if err = blob.checkFreed(); err != nil { 123 | return 124 | } 125 | if pos < 1 { 126 | err = ECGO_INVALID_LENGTH_OR_OFFSET.throw() 127 | return 128 | } 129 | if !blob.updateable { 130 | err = ECGO_RESULTSET_IS_READ_ONLY.throw() 131 | return 132 | } 133 | pos -= 1 134 | if blob.local || blob.fetchAll { 135 | if int64(pos) > blob.length { 136 | err = ECGO_INVALID_LENGTH_OR_OFFSET.throw() 137 | return 138 | } 139 | blob.setLocalData(pos, src) 140 | n = len(src) 141 | } else { 142 | if err = blob.connection.checkClosed(); err != nil { 143 | return -1, err 144 | } 145 | var writeLen, err = blob.connection.Access.dm_build_542(blob, pos, src) 146 | if err != nil { 147 | return -1, err 148 | } 149 | 150 | if blob.groupId == -1 { 151 | blob.setLocalData(pos, src) 152 | } else { 153 | blob.inRow = false 154 | blob.length = -1 155 | } 156 | n = writeLen 157 | 158 | } 159 | blob.modify = true 160 | return 161 | } 162 | 163 | func (blob *DmBlob) Truncate(length int64) error { 164 | var err error 165 | if err = blob.checkFreed(); err != nil { 166 | return err 167 | } 168 | if length < 0 { 169 | return ECGO_INVALID_LENGTH_OR_OFFSET.throw() 170 | } 171 | if !blob.updateable { 172 | return ECGO_RESULTSET_IS_READ_ONLY.throw() 173 | } 174 | if blob.local || blob.fetchAll { 175 | if length >= int64(len(blob.data)) { 176 | return nil 177 | } 178 | tmp := make([]byte, length) 179 | Dm_build_1219.Dm_build_1275(tmp, 0, blob.data, 0, len(tmp)) 180 | blob.data = tmp 181 | blob.length = int64(len(tmp)) 182 | } else { 183 | if err = blob.connection.checkClosed(); err != nil { 184 | return err 185 | } 186 | blob.length, err = blob.connection.Access.dm_build_556(&blob.lob, int(length)) 187 | if err != nil { 188 | return err 189 | } 190 | if blob.groupId == -1 { 191 | tmp := make([]byte, blob.length) 192 | Dm_build_1219.Dm_build_1275(tmp, 0, blob.data, 0, int(blob.length)) 193 | blob.data = tmp 194 | } 195 | } 196 | blob.modify = true 197 | return nil 198 | } 199 | 200 | func (dest *DmBlob) Scan(src interface{}) error { 201 | if dest == nil { 202 | return ECGO_STORE_IN_NIL_POINTER.throw() 203 | } 204 | switch src := src.(type) { 205 | case nil: 206 | *dest = *new(DmBlob) 207 | return nil 208 | case []byte: 209 | *dest = *NewBlob(src) 210 | return nil 211 | case *DmBlob: 212 | *dest = *src 213 | return nil 214 | default: 215 | return UNSUPPORTED_SCAN 216 | } 217 | } 218 | 219 | func (blob *DmBlob) getBytes(pos int64, length int32) ([]byte, error) { 220 | var err error 221 | var leaveLength int64 222 | if err = blob.checkFreed(); err != nil { 223 | return nil, err 224 | } 225 | if pos < 1 || length < 0 { 226 | return nil, ECGO_INVALID_LENGTH_OR_OFFSET.throw() 227 | } 228 | pos = pos - 1 229 | if leaveLength, err = blob.GetLength(); err != nil { 230 | return nil, err 231 | } 232 | leaveLength -= pos 233 | if leaveLength < 0 { 234 | return nil, ECGO_INVALID_LENGTH_OR_OFFSET.throw() 235 | } 236 | if int64(length) > leaveLength { 237 | length = int32(leaveLength) 238 | } 239 | if blob.local || blob.inRow || blob.fetchAll { 240 | return blob.data[pos : pos+int64(length)], nil 241 | } else { 242 | 243 | return blob.connection.Access.dm_build_505(blob, int32(pos), length) 244 | } 245 | } 246 | 247 | func (blob *DmBlob) loadAllData() { 248 | blob.checkFreed() 249 | if blob.local || blob.inRow || blob.fetchAll { 250 | return 251 | } 252 | len, _ := blob.GetLength() 253 | blob.data, _ = blob.getBytes(1, int32(len)) 254 | blob.fetchAll = true 255 | } 256 | 257 | func (blob *DmBlob) setLocalData(pos int, p []byte) { 258 | if pos+len(p) >= int(blob.length) { 259 | var tmp = make([]byte, pos+len(p)) 260 | Dm_build_1219.Dm_build_1275(tmp, 0, blob.data, 0, pos) 261 | Dm_build_1219.Dm_build_1275(tmp, pos, p, 0, len(p)) 262 | blob.data = tmp 263 | } else { 264 | Dm_build_1219.Dm_build_1275(blob.data, pos, p, 0, len(p)) 265 | } 266 | blob.length = int64(len(blob.data)) 267 | } 268 | -------------------------------------------------------------------------------- /l.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | package dm 6 | 7 | import ( 8 | "io" 9 | ) 10 | 11 | type DmClob struct { 12 | lob 13 | data []rune 14 | serverEncoding string 15 | } 16 | 17 | func newDmClob() *DmClob { 18 | return &DmClob{ 19 | lob: lob{ 20 | inRow: true, 21 | groupId: -1, 22 | fileId: -1, 23 | pageNo: -1, 24 | readOver: false, 25 | local: true, 26 | updateable: true, 27 | length: -1, 28 | compatibleOracle: false, 29 | fetchAll: false, 30 | freed: false, 31 | modify: false, 32 | }, 33 | } 34 | } 35 | 36 | func newClobFromDB(value []byte, conn *Connection, column *column, fetchAll bool) *DmClob { 37 | var clob = newDmClob() 38 | clob.connection = conn 39 | clob.lobFlag = LOB_FLAG_CHAR 40 | clob.compatibleOracle = conn.CompatibleOracle() 41 | clob.local = false 42 | clob.updateable = !column.readonly 43 | clob.tabId = column.lobTabId 44 | clob.colId = column.lobColId 45 | 46 | clob.inRow = Dm_build_1219.Dm_build_1312(value, NBLOB_HEAD_IN_ROW_FLAG) == LOB_IN_ROW 47 | clob.blobId = Dm_build_1219.Dm_build_1326(value, NBLOB_HEAD_BLOBID) 48 | if !clob.inRow { 49 | clob.groupId = Dm_build_1219.Dm_build_1316(value, NBLOB_HEAD_OUTROW_GROUPID) 50 | clob.fileId = Dm_build_1219.Dm_build_1316(value, NBLOB_HEAD_OUTROW_FILEID) 51 | clob.pageNo = Dm_build_1219.Dm_build_1321(value, NBLOB_HEAD_OUTROW_PAGENO) 52 | } 53 | if conn.NewLobFlag { 54 | clob.tabId = Dm_build_1219.Dm_build_1321(value, NBLOB_EX_HEAD_TABLE_ID) 55 | clob.colId = Dm_build_1219.Dm_build_1316(value, NBLOB_EX_HEAD_COL_ID) 56 | clob.rowId = Dm_build_1219.Dm_build_1326(value, NBLOB_EX_HEAD_ROW_ID) 57 | clob.exGroupId = Dm_build_1219.Dm_build_1316(value, NBLOB_EX_HEAD_FPA_GRPID) 58 | clob.exFileId = Dm_build_1219.Dm_build_1316(value, NBLOB_EX_HEAD_FPA_FILEID) 59 | clob.exPageNo = Dm_build_1219.Dm_build_1321(value, NBLOB_EX_HEAD_FPA_PAGENO) 60 | } 61 | clob.resetCurrentInfo() 62 | 63 | clob.serverEncoding = conn.getServerEncoding() 64 | if clob.inRow { 65 | if conn.NewLobFlag { 66 | clob.data = []rune(Dm_build_1219.Dm_build_1376(value, NBLOB_EX_HEAD_SIZE, int(clob.getLengthFromHead(value)), clob.serverEncoding, conn)) 67 | } else { 68 | clob.data = []rune(Dm_build_1219.Dm_build_1376(value, NBLOB_INROW_HEAD_SIZE, int(clob.getLengthFromHead(value)), clob.serverEncoding, conn)) 69 | } 70 | clob.length = int64(len(clob.data)) 71 | } else if fetchAll { 72 | clob.loadAllData() 73 | } 74 | return clob 75 | } 76 | 77 | func newClobOfLocal(value string, conn *Connection) *DmClob { 78 | var clob = newDmClob() 79 | clob.connection = conn 80 | clob.lobFlag = LOB_FLAG_CHAR 81 | clob.data = []rune(value) 82 | clob.length = int64(len(clob.data)) 83 | return clob 84 | } 85 | 86 | func NewClob(value string) *DmClob { 87 | var clob = newDmClob() 88 | 89 | clob.lobFlag = LOB_FLAG_CHAR 90 | clob.data = []rune(value) 91 | clob.length = int64(len(clob.data)) 92 | return clob 93 | } 94 | 95 | func (clob *DmClob) ReadString(pos int, length int) (result string, err error) { 96 | result, err = clob.getSubString(int64(pos), int32(length)) 97 | if err != nil { 98 | return 99 | } 100 | if len(result) == 0 { 101 | err = io.EOF 102 | return 103 | } 104 | return 105 | } 106 | 107 | func (clob *DmClob) WriteString(pos int, s string) (n int, err error) { 108 | if err = clob.checkFreed(); err != nil { 109 | return 110 | } 111 | if pos < 1 { 112 | err = ECGO_INVALID_LENGTH_OR_OFFSET.throw() 113 | return 114 | } 115 | if !clob.updateable { 116 | err = ECGO_RESULTSET_IS_READ_ONLY.throw() 117 | return 118 | } 119 | pos -= 1 120 | if clob.local || clob.fetchAll { 121 | if int64(pos) > clob.length { 122 | err = ECGO_INVALID_LENGTH_OR_OFFSET.throw() 123 | return 124 | } 125 | clob.setLocalData(pos, s) 126 | n = len(s) 127 | } else { 128 | if err = clob.connection.checkClosed(); err != nil { 129 | return -1, err 130 | } 131 | var writeLen, err = clob.connection.Access.dm_build_526(clob, pos, s, clob.serverEncoding) 132 | if err != nil { 133 | return -1, err 134 | } 135 | 136 | if clob.groupId == -1 { 137 | clob.setLocalData(pos, s) 138 | } else { 139 | clob.inRow = false 140 | clob.length = -1 141 | } 142 | n = writeLen 143 | } 144 | clob.modify = true 145 | return 146 | } 147 | 148 | func (clob *DmClob) Truncate(length int64) error { 149 | var err error 150 | if err = clob.checkFreed(); err != nil { 151 | return err 152 | } 153 | if length < 0 { 154 | return ECGO_INVALID_LENGTH_OR_OFFSET.throw() 155 | } 156 | if !clob.updateable { 157 | return ECGO_RESULTSET_IS_READ_ONLY.throw() 158 | } 159 | if clob.local || clob.fetchAll { 160 | if length >= int64(len(clob.data)) { 161 | return nil 162 | } 163 | clob.data = clob.data[0:length] 164 | clob.length = int64(len(clob.data)) 165 | } else { 166 | if err = clob.connection.checkClosed(); err != nil { 167 | return err 168 | } 169 | clob.length, err = clob.connection.Access.dm_build_556(&clob.lob, int(length)) 170 | if err != nil { 171 | return err 172 | } 173 | if clob.groupId == -1 { 174 | clob.data = clob.data[0:clob.length] 175 | } 176 | } 177 | clob.modify = true 178 | return nil 179 | } 180 | 181 | func (dest *DmClob) Scan(src interface{}) error { 182 | if dest == nil { 183 | return ECGO_STORE_IN_NIL_POINTER.throw() 184 | } 185 | switch src := src.(type) { 186 | case nil: 187 | *dest = *new(DmClob) 188 | return nil 189 | case string: 190 | *dest = *NewClob(src) 191 | return nil 192 | case *DmClob: 193 | *dest = *src 194 | return nil 195 | default: 196 | return UNSUPPORTED_SCAN 197 | } 198 | } 199 | 200 | func (clob *DmClob) getSubString(pos int64, len int32) (string, error) { 201 | var err error 202 | var leaveLength int64 203 | if err = clob.checkFreed(); err != nil { 204 | return "", err 205 | } 206 | if pos < 1 || len < 0 { 207 | return "", ECGO_INVALID_LENGTH_OR_OFFSET.throw() 208 | } 209 | pos = pos - 1 210 | if leaveLength, err = clob.GetLength(); err != nil { 211 | return "", err 212 | } 213 | if pos > leaveLength { 214 | pos = leaveLength 215 | } 216 | leaveLength -= pos 217 | if leaveLength < 0 { 218 | return "", ECGO_INVALID_LENGTH_OR_OFFSET.throw() 219 | } 220 | if int64(len) > leaveLength { 221 | len = int32(leaveLength) 222 | } 223 | if clob.local || clob.inRow || clob.fetchAll { 224 | if pos > clob.length { 225 | return "", ECGO_INVALID_LENGTH_OR_OFFSET.throw() 226 | } 227 | return string(clob.data[pos : pos+int64(len)]), nil 228 | } else { 229 | 230 | return clob.connection.Access.dm_build_515(clob, int32(pos), len) 231 | } 232 | } 233 | 234 | func (clob *DmClob) loadAllData() { 235 | clob.checkFreed() 236 | if clob.local || clob.inRow || clob.fetchAll { 237 | return 238 | } 239 | len, _ := clob.GetLength() 240 | s, _ := clob.getSubString(1, int32(len)) 241 | clob.data = []rune(s) 242 | clob.fetchAll = true 243 | } 244 | 245 | func (clob *DmClob) setLocalData(pos int, str string) { 246 | if pos+len(str) >= int(clob.length) { 247 | clob.data = []rune(string(clob.data[0:pos]) + str) 248 | } else { 249 | clob.data = []rune(string(clob.data[0:pos]) + str + string(clob.data[pos+len(str):len(clob.data)])) 250 | } 251 | clob.length = int64(len(clob.data)) 252 | } 253 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | package dm 6 | 7 | import ( 8 | "context" 9 | "database/sql" 10 | "database/sql/driver" 11 | "sync" 12 | 13 | "github.com/gotomicro/dmgo/i18n" 14 | ) 15 | 16 | // 发版标记 17 | //var version = "8.1.2.38" 18 | //var build_date = "2021.07.14" 19 | //var svn = "7050" 20 | 21 | var globalDmDriver = newDmDriver() 22 | 23 | func init() { 24 | sql.Register("dm", globalDmDriver) 25 | } 26 | 27 | func driverInit() { 28 | switch Locale { 29 | case 0: 30 | i18n.InitConfig(i18n.Messages_zh_CN) 31 | case 1: 32 | i18n.InitConfig(i18n.Messages_en_US) 33 | case 2: 34 | i18n.InitConfig(i18n.Messages_zh_TW) 35 | } 36 | } 37 | 38 | type Driver struct { 39 | filterable 40 | readPropMutex sync.Mutex 41 | } 42 | 43 | func newDmDriver() *Driver { 44 | d := new(Driver) 45 | d.idGenerator = dmDriverIDGenerator 46 | return d 47 | } 48 | 49 | func (d *Driver) Open(dsn string) (driver.Conn, error) { 50 | return d.open(dsn) 51 | } 52 | 53 | func (d *Driver) OpenConnector(dsn string) (driver.Connector, error) { 54 | return d.openConnector(dsn) 55 | } 56 | 57 | func (d *Driver) open(dsn string) (*Connection, error) { 58 | c, err := d.openConnector(dsn) 59 | if err != nil { 60 | return nil, err 61 | } 62 | return c.connect(context.Background()) 63 | } 64 | 65 | func (d *Driver) openConnector(dsn string) (*Connector, error) { 66 | connector := new(Connector).init() 67 | connector.url = dsn 68 | connector.dmDriver = d 69 | d.readPropMutex.Lock() 70 | err := connector.mergeConfigs(dsn) 71 | d.readPropMutex.Unlock() 72 | if err != nil { 73 | return nil, err 74 | } 75 | connector.createFilterChain(connector, nil) 76 | return connector, nil 77 | } 78 | -------------------------------------------------------------------------------- /o.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | package dm 6 | 7 | import ( 8 | "math/big" 9 | "reflect" 10 | "strconv" 11 | "strings" 12 | ) 13 | 14 | const ( 15 | XDEC_MAX_PREC int = 38 16 | XDEC_SIZE = 21 17 | 18 | FLAG_ZERO int = 0x80 19 | FLAG_POSITIVE int = 0xC1 20 | FLAG_NEGTIVE int = 0x3E 21 | EXP_MAX int = 0xFF - 1 - FLAG_POSITIVE 22 | EXP_MIN int = FLAG_NEGTIVE + 1 - 0x7F 23 | 24 | NUM_POSITIVE int = 1 25 | NUM_NEGTIVE int = 101 26 | ) 27 | 28 | type DmDecimal struct { 29 | sign int 30 | weight int 31 | prec int 32 | scale int 33 | digits string 34 | } 35 | 36 | func NewDecimalFromInt64(x int64) (*DmDecimal, error) { 37 | return NewDecimalFromBigInt(big.NewInt(x)) 38 | } 39 | func (d DmDecimal) ToInt64() int64 { 40 | return d.ToBigInt().Int64() 41 | } 42 | func NewDecimalFromFloat64(x float64) (*DmDecimal, error) { 43 | return NewDecimalFromBigFloat(big.NewFloat(x)) 44 | } 45 | func (d DmDecimal) ToFloat64() float64 { 46 | f, _ := d.ToBigFloat().Float64() 47 | return f 48 | } 49 | func NewDecimalFromBigInt(bigInt *big.Int) (*DmDecimal, error) { 50 | return newDecimal(bigInt, len(bigInt.String()), 0) 51 | } 52 | func (d DmDecimal) ToBigInt() *big.Int { 53 | if d.isZero() { 54 | return big.NewInt(0) 55 | } 56 | var digits = d.digits 57 | if d.sign < 0 { 58 | digits = "-" + digits 59 | } 60 | i1, ok := new(big.Int).SetString(digits, 10) 61 | if !ok { 62 | return nil 63 | } 64 | if d.weight > 0 { 65 | i2, ok := new(big.Int).SetString("1"+strings.Repeat("0", d.weight), 10) 66 | if !ok { 67 | return nil 68 | } 69 | i1.Mul(i1, i2) 70 | } else if d.weight < 0 { 71 | i2, ok := new(big.Int).SetString("1"+strings.Repeat("0", -d.weight), 10) 72 | if !ok { 73 | return nil 74 | } 75 | i1.Quo(i1, i2) 76 | } 77 | return i1 78 | } 79 | func NewDecimalFromBigFloat(bigFloat *big.Float) (*DmDecimal, error) { 80 | return newDecimal(bigFloat, int(bigFloat.Prec()), int(bigFloat.Prec())) 81 | } 82 | func (d DmDecimal) ToBigFloat() *big.Float { 83 | if d.isZero() { 84 | return big.NewFloat(0.0) 85 | } 86 | var digits = d.digits 87 | if d.sign < 0 { 88 | digits = "-" + digits 89 | } 90 | f1, ok := new(big.Float).SetString(digits) 91 | if !ok { 92 | return nil 93 | } 94 | if d.weight > 0 { 95 | f2, ok := new(big.Float).SetString("1" + strings.Repeat("0", d.weight)) 96 | if !ok { 97 | return nil 98 | } 99 | f1.Mul(f1, f2) 100 | } else if d.weight < 0 { 101 | f2, ok := new(big.Float).SetString("1" + strings.Repeat("0", -d.weight)) 102 | if !ok { 103 | return nil 104 | } 105 | f1.Quo(f1, f2) 106 | } 107 | return f1 108 | } 109 | 110 | func NewDecimalFromString(s string) (*DmDecimal, error) { 111 | num, ok := new(big.Float).SetString(strings.TrimSpace(s)) 112 | if !ok { 113 | return nil, ECGO_DATA_CONVERTION_ERROR.throw() 114 | } 115 | return NewDecimalFromBigFloat(num) 116 | } 117 | 118 | func (d DmDecimal) String() string { 119 | 120 | if d.isZero() { 121 | return "0" 122 | } 123 | digitsStr := d.digits 124 | if d.weight > 0 { 125 | digitsStr = digitsStr + strings.Repeat("0", d.weight) 126 | } else if d.weight < 0 { 127 | digitsStr = strings.Repeat("0", -d.weight+1) + digitsStr 128 | } 129 | 130 | if digitsStr[0] == '0' && digitsStr[1] != '.' { 131 | digitsStr = digitsStr[1:] 132 | } 133 | 134 | if digitsStr[len(digitsStr)-1] == '0' && strings.IndexRune(digitsStr, '.') >= 0 { 135 | digitsStr = digitsStr[0 : len(digitsStr)-1] 136 | } 137 | 138 | if d.sign < 0 { 139 | digitsStr = "-" + digitsStr 140 | } 141 | 142 | return digitsStr 143 | } 144 | 145 | func (d DmDecimal) Sign() int { 146 | return d.sign 147 | } 148 | 149 | func (dest *DmDecimal) Scan(src interface{}) error { 150 | if dest == nil { 151 | return ECGO_STORE_IN_NIL_POINTER.throw() 152 | } 153 | switch src := src.(type) { 154 | case nil: 155 | *dest = *new(DmDecimal) 156 | return nil 157 | case int, int8, int16, int32, int64: 158 | d, err := NewDecimalFromInt64(reflect.ValueOf(src).Int()) 159 | if err != nil { 160 | return err 161 | } 162 | *dest = *d 163 | return nil 164 | case uint, uint8, uint16, uint32, uint64: 165 | d, err := NewDecimalFromBigInt(new(big.Int).SetUint64(reflect.ValueOf(src).Uint())) 166 | if err != nil { 167 | return err 168 | } 169 | *dest = *d 170 | return nil 171 | case string: 172 | d, err := NewDecimalFromString(src) 173 | if err != nil { 174 | return err 175 | } 176 | *dest = *d 177 | return nil 178 | case *DmDecimal: 179 | *dest = *src 180 | return nil 181 | default: 182 | return UNSUPPORTED_SCAN 183 | } 184 | } 185 | 186 | func newDecimal(dec interface{}, prec int, scale int) (*DmDecimal, error) { 187 | d := &DmDecimal{ 188 | prec: prec, 189 | scale: scale, 190 | } 191 | if isFloat(DECIMAL, scale) { 192 | d.prec = getFloatPrec(prec) 193 | d.scale = -1 194 | } 195 | switch de := dec.(type) { 196 | case *big.Int: 197 | d.sign = de.Sign() 198 | 199 | if d.isZero() { 200 | return d, nil 201 | } 202 | str := de.String() 203 | 204 | if d.sign < 0 { 205 | str = str[1:] 206 | } 207 | 208 | if err := checkPrec(len(str), prec); err != nil { 209 | return d, err 210 | } 211 | i := 0 212 | istart := len(str) - 1 213 | 214 | for i = istart; i > 0; i-- { 215 | if str[i] != '0' { 216 | break 217 | } 218 | } 219 | str = str[:i+1] 220 | d.weight += istart - i 221 | 222 | if isOdd(d.weight) { 223 | str += "0" 224 | d.weight -= 1 225 | } 226 | if isOdd(len(str)) { 227 | str = "0" + str 228 | } 229 | d.digits = str 230 | case *big.Float: 231 | d.sign = de.Sign() 232 | 233 | if d.isZero() { 234 | return d, nil 235 | } 236 | str := de.Text('f', -1) 237 | 238 | if d.sign < 0 { 239 | str = str[1:] 240 | } 241 | 242 | pointIndex := strings.IndexByte(str, '.') 243 | i, istart, length := 0, 0, len(str) 244 | 245 | if pointIndex != -1 { 246 | if str[0] == '0' { 247 | 248 | istart = 2 249 | for i = istart; i < length; i++ { 250 | if str[i] != '0' { 251 | break 252 | } 253 | } 254 | str = str[i:] 255 | d.weight -= i - istart + len(str) 256 | } else { 257 | str = str[:pointIndex] + str[pointIndex+1:] 258 | d.weight -= length - pointIndex - 1 259 | } 260 | } 261 | 262 | length = len(str) 263 | istart = length - 1 264 | for i = istart; i > 0; i-- { 265 | if str[i] != '0' { 266 | break 267 | } 268 | } 269 | str = str[:i+1] + str[length:] 270 | d.weight += istart - i 271 | 272 | if isOdd(d.weight) { 273 | str += "0" 274 | d.weight -= 1 275 | } 276 | if isOdd(len(str)) { 277 | str = "0" + str 278 | } 279 | d.digits = str 280 | case []byte: 281 | return decodeDecimal(de, prec, scale) 282 | } 283 | return d, nil 284 | } 285 | 286 | func (d DmDecimal) encodeDecimal() ([]byte, error) { 287 | if d.isZero() { 288 | return []byte{byte(FLAG_ZERO)}, nil 289 | } 290 | exp := (d.weight+len(d.digits))/2 - 1 291 | if exp > EXP_MAX || exp < EXP_MIN { 292 | return nil, ECGO_DATA_TOO_LONG.throw() 293 | } 294 | validLen := len(d.digits)/2 + 1 295 | 296 | if d.sign < 0 && validLen >= XDEC_SIZE { 297 | validLen = XDEC_SIZE - 1 298 | } else if validLen > XDEC_SIZE { 299 | validLen = XDEC_SIZE 300 | } 301 | retLen := validLen 302 | if d.sign < 0 { 303 | retLen = validLen + 1 304 | } 305 | retBytes := make([]byte, retLen) 306 | if d.sign > 0 { 307 | retBytes[0] = byte(exp + FLAG_POSITIVE) 308 | } else { 309 | retBytes[0] = byte(FLAG_NEGTIVE - exp) 310 | } 311 | 312 | ibytes := 1 313 | for ichar := 0; ibytes < validLen; { 314 | digit1, err := strconv.Atoi(string(d.digits[ichar])) 315 | if err != nil { 316 | return nil, err 317 | } 318 | ichar++ 319 | digit2, err := strconv.Atoi(string(d.digits[ichar])) 320 | ichar++ 321 | if err != nil { 322 | return nil, err 323 | } 324 | 325 | digit := digit1*10 + digit2 326 | if d.sign > 0 { 327 | retBytes[ibytes] = byte(digit + NUM_POSITIVE) 328 | } else { 329 | retBytes[ibytes] = byte(NUM_NEGTIVE - digit) 330 | } 331 | ibytes++ 332 | } 333 | if d.sign < 0 && ibytes < retLen { 334 | retBytes[ibytes] = 0x66 335 | ibytes++ 336 | } 337 | if ibytes < retLen { 338 | retBytes[ibytes] = 0x00 339 | } 340 | return retBytes, nil 341 | } 342 | 343 | func decodeDecimal(values []byte, prec int, scale int) (*DmDecimal, error) { 344 | var decimal = &DmDecimal{ 345 | prec: prec, 346 | scale: scale, 347 | sign: 0, 348 | weight: 0, 349 | } 350 | if values == nil || len(values) == 0 || len(values) > XDEC_SIZE { 351 | return nil, ECGO_FATAL_ERROR.throw() 352 | } 353 | if values[0] == byte(FLAG_ZERO) || len(values) == 1 { 354 | return decimal, nil 355 | } 356 | if values[0]&byte(FLAG_ZERO) != 0 { 357 | decimal.sign = 1 358 | } else { 359 | decimal.sign = -1 360 | } 361 | 362 | var flag = int(Dm_build_1219.Dm_build_1339(values, 0)) 363 | var exp int 364 | if decimal.sign > 0 { 365 | exp = flag - FLAG_POSITIVE 366 | } else { 367 | exp = FLAG_NEGTIVE - flag 368 | } 369 | var digit = 0 370 | var sf = "" 371 | for ival := 1; ival < len(values); ival++ { 372 | if decimal.sign > 0 { 373 | digit = int(values[ival]) - NUM_POSITIVE 374 | } else { 375 | digit = NUM_NEGTIVE - int(values[ival]) 376 | } 377 | if digit < 0 || digit > 99 { 378 | break 379 | } 380 | if digit < 10 { 381 | sf += "0" 382 | } 383 | sf += strconv.Itoa(digit) 384 | } 385 | decimal.digits = sf 386 | decimal.weight = exp*2 - (len(decimal.digits) - 2) 387 | 388 | return decimal, nil 389 | } 390 | 391 | func (d DmDecimal) isZero() bool { 392 | return d.sign == 0 393 | } 394 | 395 | func checkPrec(len int, prec int) error { 396 | if prec > 0 && len > prec || len > XDEC_MAX_PREC { 397 | return ECGO_DATA_TOO_LONG.throw() 398 | } 399 | return nil 400 | } 401 | 402 | func isOdd(val int) bool { 403 | return val%2 != 0 404 | } 405 | -------------------------------------------------------------------------------- /parser/zt.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | package parser 6 | 7 | import "strconv" 8 | 9 | const ( 10 | MAX_DEC_LEN = 38 11 | ) 12 | 13 | const ( 14 | NORMAL int = iota 15 | INT 16 | DOUBLE 17 | DECIMAL 18 | STRING 19 | HEX_INT 20 | WHITESPACE_OR_COMMENT 21 | NULL 22 | ) 23 | 24 | type LVal struct { 25 | Value string 26 | Tp int 27 | Position int 28 | } 29 | 30 | // 31 | //func newLValNoParams() *LVal { 32 | // return new(LVal).reset() 33 | //} 34 | 35 | func newLVal(value string, tp int) *LVal { 36 | return &LVal{Value: value, Tp: tp} 37 | } 38 | 39 | func (l *LVal) reset() *LVal { 40 | l.Value = "" 41 | l.Tp = NORMAL 42 | return l 43 | } 44 | 45 | func (l *LVal) String() string { 46 | return strconv.Itoa(l.Tp) + ":" + l.Value 47 | } 48 | -------------------------------------------------------------------------------- /r.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | package dm 6 | 7 | import ( 8 | "math" 9 | "strconv" 10 | "strings" 11 | 12 | "github.com/gotomicro/dmgo/util" 13 | ) 14 | 15 | const ( 16 | QUA_Y = 0 17 | QUA_YM = 1 18 | QUA_MO = 2 19 | ) 20 | 21 | type DmIntervalYM struct { 22 | leadScale int 23 | isLeadScaleSet bool 24 | _type byte 25 | years int 26 | months int 27 | scaleForSvr int 28 | } 29 | 30 | func NewDmIntervalYMByString(str string) (ym *DmIntervalYM, err error) { 31 | defer func() { 32 | if p := recover(); p != nil { 33 | err = ECGO_INVALID_TIME_INTERVAL.throw() 34 | } 35 | }() 36 | ym = new(DmIntervalYM) 37 | ym.isLeadScaleSet = false 38 | if err = ym.parseIntervYMString(strings.TrimSpace(str)); err != nil { 39 | return nil, err 40 | } 41 | return ym, nil 42 | } 43 | 44 | func newDmIntervalYMByBytes(bytes []byte) *DmIntervalYM { 45 | ym := new(DmIntervalYM) 46 | 47 | ym.scaleForSvr = int(Dm_build_1219.Dm_build_1321(bytes, 8)) 48 | ym.leadScale = (ym.scaleForSvr >> 4) & 0x0000000F 49 | ym._type = bytes[9] 50 | switch ym._type { 51 | case QUA_Y: 52 | ym.years = int(Dm_build_1219.Dm_build_1321(bytes, 0)) 53 | case QUA_YM: 54 | ym.years = int(Dm_build_1219.Dm_build_1321(bytes, 0)) 55 | ym.months = int(Dm_build_1219.Dm_build_1321(bytes, 4)) 56 | case QUA_MO: 57 | ym.months = int(Dm_build_1219.Dm_build_1321(bytes, 4)) 58 | } 59 | return ym 60 | } 61 | 62 | func (ym *DmIntervalYM) GetYear() int { 63 | return ym.years 64 | } 65 | 66 | func (ym *DmIntervalYM) GetMonth() int { 67 | return ym.months 68 | } 69 | 70 | func (ym *DmIntervalYM) GetYMType() byte { 71 | return ym._type 72 | } 73 | 74 | func (ym *DmIntervalYM) String() string { 75 | str := "INTERVAL " 76 | var year, month string 77 | var l int 78 | var destLen int 79 | 80 | switch ym._type { 81 | case QUA_Y: 82 | year = strconv.FormatInt(int64(math.Abs(float64(ym.years))), 10) 83 | if ym.years < 0 { 84 | str += "-" 85 | } 86 | 87 | if ym.leadScale > len(year) { 88 | l = len(year) 89 | destLen = ym.leadScale 90 | 91 | for destLen > l { 92 | year = "0" + year 93 | destLen-- 94 | } 95 | } 96 | 97 | str += "'" + year + "' YEAR(" + strconv.FormatInt(int64(ym.leadScale), 10) + ")" 98 | case QUA_YM: 99 | year = strconv.FormatInt(int64(math.Abs(float64(ym.years))), 10) 100 | month = strconv.FormatInt(int64(math.Abs(float64(ym.months))), 10) 101 | 102 | if ym.years < 0 || ym.months < 0 { 103 | str += "-" 104 | } 105 | 106 | if ym.leadScale > len(year) { 107 | l = len(year) 108 | destLen = ym.leadScale 109 | 110 | for destLen > l { 111 | year = "0" + year 112 | destLen-- 113 | } 114 | } 115 | 116 | if len(month) < 2 { 117 | month = "0" + month 118 | } 119 | 120 | str += "'" + year + "-" + month + "' YEAR(" + strconv.FormatInt(int64(ym.leadScale), 10) + ") TO MONTH" 121 | case QUA_MO: 122 | 123 | month = strconv.FormatInt(int64(math.Abs(float64(ym.months))), 10) 124 | if ym.months < 0 { 125 | str += "-" 126 | } 127 | 128 | if ym.leadScale > len(month) { 129 | l = len(month) 130 | destLen = ym.leadScale 131 | for destLen > l { 132 | month = "0" + month 133 | destLen-- 134 | } 135 | } 136 | 137 | str += "'" + month + "' MONTH(" + strconv.FormatInt(int64(ym.leadScale), 10) + ")" 138 | } 139 | return str 140 | } 141 | 142 | func (dest *DmIntervalYM) Scan(src interface{}) error { 143 | if dest == nil { 144 | return ECGO_STORE_IN_NIL_POINTER.throw() 145 | } 146 | switch src := src.(type) { 147 | case nil: 148 | *dest = *new(DmIntervalYM) 149 | return nil 150 | case *DmIntervalYM: 151 | *dest = *src 152 | return nil 153 | case string: 154 | ret, err := NewDmIntervalYMByString(src) 155 | if err != nil { 156 | return err 157 | } 158 | *dest = *ret 159 | return nil 160 | default: 161 | return UNSUPPORTED_SCAN 162 | } 163 | } 164 | 165 | func (ym *DmIntervalYM) parseIntervYMString(str string) error { 166 | str = strings.ToUpper(str) 167 | ret := strings.Split(str, " ") 168 | l := len(ret) 169 | if l < 3 || !util.StringUtil.EqualsIgnoreCase(ret[0], "INTERVAL") || !(strings.HasPrefix(ret[2], "YEAR") || strings.HasPrefix(ret[2], "MONTH")) { 170 | return ECGO_INVALID_TIME_INTERVAL.throw() 171 | } 172 | ym._type = QUA_YM 173 | yearId := strings.Index(str, "YEAR") 174 | monthId := strings.Index(str, "MONTH") 175 | toId := strings.Index(str, "TO") 176 | var err error 177 | if toId == -1 { 178 | if yearId != -1 && monthId == -1 { 179 | ym._type = QUA_Y 180 | ym.leadScale, err = ym.getLeadPrec(str, yearId) 181 | if err != nil { 182 | return err 183 | } 184 | } else if monthId != -1 && yearId == -1 { 185 | ym._type = QUA_MO 186 | ym.leadScale, err = ym.getLeadPrec(str, monthId) 187 | if err != nil { 188 | return err 189 | } 190 | } else { 191 | return ECGO_INVALID_TIME_INTERVAL.throw() 192 | } 193 | } else { 194 | if yearId == -1 || monthId == -1 { 195 | return ECGO_INVALID_TIME_INTERVAL.throw() 196 | } 197 | ym._type = QUA_YM 198 | ym.leadScale, err = ym.getLeadPrec(str, yearId) 199 | if err != nil { 200 | return err 201 | } 202 | } 203 | 204 | ym.scaleForSvr = (int(ym._type) << 8) + (ym.leadScale << 4) 205 | timeVals, err := ym.getTimeValue(ret[1], int(ym._type)) 206 | if err != nil { 207 | return err 208 | } 209 | ym.years = timeVals[0] 210 | ym.months = timeVals[1] 211 | return ym.checkScale(ym.leadScale) 212 | } 213 | 214 | func (ym *DmIntervalYM) getLeadPrec(str string, startIndex int) (int, error) { 215 | if ym.isLeadScaleSet { 216 | return ym.leadScale, nil 217 | } 218 | 219 | leftBtId := strings.Index(str[startIndex:], "(") 220 | rightBtId := strings.Index(str[startIndex:], ")") 221 | leadPrec := 0 222 | 223 | if rightBtId == -1 && leftBtId == -1 { 224 | leftBtId += startIndex 225 | rightBtId += startIndex 226 | l := strings.Index(str, "'") 227 | var r int 228 | var dataStr string 229 | if l != -1 { 230 | r = strings.Index(str[l+1:], "'") 231 | if r != -1 { 232 | r += l + 1 233 | } 234 | } else { 235 | r = -1 236 | } 237 | 238 | if r != -1 { 239 | dataStr = strings.TrimSpace(str[l+1 : r]) 240 | } else { 241 | dataStr = "" 242 | } 243 | 244 | if dataStr != "" { 245 | sign := dataStr[0] 246 | if sign == '+' || sign == '-' { 247 | dataStr = strings.TrimSpace(dataStr[1:]) 248 | } 249 | end := strings.Index(dataStr, "-") 250 | 251 | if end != -1 { 252 | dataStr = dataStr[:end] 253 | } 254 | 255 | leadPrec = len(dataStr) 256 | } else { 257 | leadPrec = 2 258 | } 259 | } else if rightBtId != -1 && leftBtId != -1 && rightBtId > leftBtId+1 { 260 | leftBtId += startIndex 261 | rightBtId += startIndex 262 | strPrec := strings.TrimSpace(str[leftBtId+1 : rightBtId]) 263 | temp, err := strconv.ParseInt(strPrec, 10, 32) 264 | if err != nil { 265 | return 0, err 266 | } 267 | 268 | leadPrec = int(temp) 269 | } else { 270 | return 0, ECGO_INVALID_TIME_INTERVAL.throw() 271 | } 272 | 273 | return leadPrec, nil 274 | } 275 | 276 | func (ym *DmIntervalYM) checkScale(prec int) error { 277 | switch ym._type { 278 | case QUA_Y: 279 | if prec < len(strconv.FormatInt(int64(math.Abs(float64(ym.years))), 10)) { 280 | return ECGO_INVALID_TIME_INTERVAL.throw() 281 | } 282 | case QUA_YM: 283 | if prec < len(strconv.FormatInt(int64(math.Abs(float64(ym.years))), 10)) { 284 | return ECGO_INVALID_TIME_INTERVAL.throw() 285 | } 286 | 287 | if int64(math.Abs(float64(ym.months))) > 11 { 288 | return ECGO_INVALID_TIME_INTERVAL.throw() 289 | } 290 | 291 | case QUA_MO: 292 | if prec < len(strconv.FormatInt(int64(math.Abs(float64(ym.months))), 10)) { 293 | return ECGO_INVALID_TIME_INTERVAL.throw() 294 | } 295 | } 296 | return nil 297 | } 298 | 299 | func (ym *DmIntervalYM) getTimeValue(subStr string, _type int) ([]int, error) { 300 | hasQuate := false 301 | if subStr[0] == '\'' && subStr[len(subStr)-1] == '\'' { 302 | hasQuate = true 303 | subStr = strings.TrimSpace(subStr[1 : len(subStr)-1]) 304 | } 305 | 306 | negative := false 307 | if strings.Index(subStr, "-") == 0 { 308 | negative = true 309 | subStr = subStr[1:] 310 | } else if strings.Index(subStr, "+") == 0 { 311 | negative = false 312 | subStr = subStr[1:] 313 | } 314 | 315 | if subStr[0] == '\'' && subStr[len(subStr)-1] == '\'' { 316 | hasQuate = true 317 | subStr = strings.TrimSpace(subStr[1 : len(subStr)-1]) 318 | } 319 | 320 | if !hasQuate { 321 | return nil, ECGO_INVALID_TIME_INTERVAL.throw() 322 | } 323 | 324 | lastSignIndex := strings.LastIndex(subStr, "-") 325 | 326 | list := make([]string, 2) 327 | if lastSignIndex == -1 || lastSignIndex == 0 { 328 | list[0] = subStr 329 | list[1] = "" 330 | } else { 331 | list[0] = subStr[0:lastSignIndex] 332 | list[1] = subStr[lastSignIndex+1:] 333 | } 334 | 335 | var yearVal, monthVal int64 336 | var err error 337 | if ym._type == QUA_YM { 338 | yearVal, err = strconv.ParseInt(list[0], 10, 32) 339 | if err != nil { 340 | return nil, err 341 | } 342 | 343 | if util.StringUtil.EqualsIgnoreCase(list[1], "") { 344 | monthVal = 0 345 | } else { 346 | monthVal, err = strconv.ParseInt(list[1], 10, 32) 347 | if err != nil { 348 | return nil, err 349 | } 350 | } 351 | 352 | if negative { 353 | yearVal *= -1 354 | monthVal *= -1 355 | } 356 | 357 | if yearVal > int64(math.Pow10(ym.leadScale))-1 || yearVal < 1-int64(math.Pow10(ym.leadScale)) { 358 | return nil, ECGO_INVALID_TIME_INTERVAL.throw() 359 | } 360 | } else if ym._type == QUA_Y { 361 | yearVal, err = strconv.ParseInt(list[0], 10, 32) 362 | if err != nil { 363 | return nil, err 364 | } 365 | monthVal = 0 366 | 367 | if negative { 368 | yearVal *= -1 369 | } 370 | 371 | if yearVal > int64(math.Pow10(ym.leadScale))-1 || yearVal < 1-int64(math.Pow10(ym.leadScale)) { 372 | return nil, ECGO_INVALID_TIME_INTERVAL.throw() 373 | } 374 | } else { 375 | yearVal = 0 376 | monthVal, err = strconv.ParseInt(list[0], 10, 32) 377 | if err != nil { 378 | return nil, err 379 | } 380 | if negative { 381 | monthVal *= -1 382 | } 383 | 384 | if monthVal > int64(math.Pow10(ym.leadScale))-1 || monthVal < 1-int64(math.Pow10(ym.leadScale)) { 385 | return nil, ECGO_INVALID_TIME_INTERVAL.throw() 386 | } 387 | } 388 | 389 | ret := make([]int, 2) 390 | ret[0] = int(yearVal) 391 | ret[1] = int(monthVal) 392 | 393 | return ret, nil 394 | } 395 | 396 | func (ym *DmIntervalYM) encode(scale int) ([]byte, error) { 397 | if scale == 0 { 398 | scale = ym.scaleForSvr 399 | } 400 | year, month := ym.years, ym.months 401 | if err := ym.checkScale(ym.leadScale); err != nil { 402 | return nil, err 403 | } 404 | if scale != ym.scaleForSvr { 405 | convertYM, err := ym.convertTo(scale) 406 | if err != nil { 407 | return nil, err 408 | } 409 | year = convertYM.years 410 | month = convertYM.months 411 | } else { 412 | if err := ym.checkScale(ym.leadScale); err != nil { 413 | return nil, err 414 | } 415 | } 416 | 417 | bytes := make([]byte, 12) 418 | Dm_build_1219.Dm_build_1235(bytes, 0, int32(year)) 419 | Dm_build_1219.Dm_build_1235(bytes, 4, int32(month)) 420 | Dm_build_1219.Dm_build_1235(bytes, 8, int32(scale)) 421 | return bytes, nil 422 | } 423 | 424 | func (ym *DmIntervalYM) convertTo(scale int) (*DmIntervalYM, error) { 425 | destType := (scale & 0x0000FF00) >> 8 426 | leadPrec := (scale >> 4) & 0x0000000F 427 | totalMonths := ym.years*12 + ym.months 428 | year := 0 429 | month := 0 430 | switch destType { 431 | case QUA_Y: 432 | year = totalMonths / 12 433 | 434 | if totalMonths%12 >= 6 { 435 | year++ 436 | } else if totalMonths%12 <= -6 { 437 | year-- 438 | } 439 | if leadPrec < len(strconv.Itoa(int(math.Abs(float64(year))))) { 440 | return nil, ECGO_INVALID_TIME_INTERVAL.throw() 441 | } 442 | case QUA_YM: 443 | year = totalMonths / 12 444 | month = totalMonths % 12 445 | if leadPrec < len(strconv.Itoa(int(math.Abs(float64(year))))) { 446 | return nil, ECGO_INVALID_TIME_INTERVAL.throw() 447 | } 448 | case QUA_MO: 449 | month = totalMonths 450 | if leadPrec < len(strconv.Itoa(int(math.Abs(float64(month))))) { 451 | return nil, ECGO_INVALID_TIME_INTERVAL.throw() 452 | } 453 | } 454 | return &DmIntervalYM{ 455 | _type: byte(destType), 456 | years: year, 457 | months: month, 458 | scaleForSvr: scale, 459 | leadScale: (scale >> 4) & 0x0000000F, 460 | }, nil 461 | } 462 | -------------------------------------------------------------------------------- /s.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | package dm 6 | 7 | type DmResult struct { 8 | filterable 9 | dmStmt *DmStatement 10 | affectedRows int64 11 | insertId int64 12 | } 13 | 14 | func newDmResult(bs *DmStatement, execInfo *execRetInfo) *DmResult { 15 | result := DmResult{} 16 | result.resetFilterable(&bs.filterable) 17 | result.dmStmt = bs 18 | result.affectedRows = execInfo.updateCount 19 | result.insertId = execInfo.lastInsertId 20 | result.idGenerator = dmResultIDGenerator 21 | 22 | return &result 23 | } 24 | 25 | /************************************************************* 26 | ** PUBLIC METHODS AND FUNCTIONS 27 | *************************************************************/ 28 | func (r *DmResult) LastInsertId() (int64, error) { 29 | //if err := r.dmStmt.checkClosed(); err != nil { 30 | // return -1, err 31 | //} 32 | if len(r.filterChain.filters) == 0 { 33 | return r.lastInsertId() 34 | } 35 | return r.filterChain.reset().DmResultLastInsertId(r) 36 | } 37 | 38 | func (r *DmResult) RowsAffected() (int64, error) { 39 | //if err := r.dmStmt.checkClosed(); err != nil { 40 | // return -1, err 41 | //} 42 | if len(r.filterChain.filters) == 0 { 43 | return r.rowsAffected() 44 | } 45 | return r.filterChain.reset().DmResultRowsAffected(r) 46 | } 47 | 48 | func (result *DmResult) lastInsertId() (int64, error) { 49 | return result.insertId, nil 50 | } 51 | 52 | func (result *DmResult) rowsAffected() (int64, error) { 53 | return result.affectedRows, nil 54 | } 55 | -------------------------------------------------------------------------------- /security/zy.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | // This is a mirror of golang.org/x/crypto/internal/subtle. 7 | package security 8 | 9 | import "unsafe" 10 | 11 | // AnyOverlap reports whether x and y share memory at any (not necessarily 12 | // corresponding) index. The memory beyond the slice length is ignored. 13 | func AnyOverlap(x, y []byte) bool { 14 | return len(x) > 0 && len(y) > 0 && 15 | uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) && 16 | uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1])) 17 | } 18 | 19 | // InexactOverlap reports whether x and y share memory at any non-corresponding 20 | // index. The memory beyond the slice length is ignored. Note that x and y can 21 | // have different lengths and still not have any inexact overlap. 22 | // 23 | // InexactOverlap can be used to implement the requirements of the crypto/cipher 24 | // AEAD, Block, BlockMode and Stream interfaces. 25 | func InexactOverlap(x, y []byte) bool { 26 | if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] { 27 | return false 28 | } 29 | return AnyOverlap(x, y) 30 | } -------------------------------------------------------------------------------- /security/zz.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package security 7 | 8 | type Cipher interface { 9 | Encrypt(plaintext []byte, genDigest bool) []byte 10 | Decrypt(ciphertext []byte, checkDigest bool) ([]byte, error) 11 | } 12 | -------------------------------------------------------------------------------- /security/zza.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package security 7 | 8 | import ( 9 | "crypto/rand" 10 | "errors" 11 | "io" 12 | "math/big" 13 | ) 14 | 15 | type dhGroup struct { 16 | p *big.Int 17 | g *big.Int 18 | } 19 | 20 | func newDhGroup(prime, generator *big.Int) *dhGroup { 21 | return &dhGroup{ 22 | p: prime, 23 | g: generator, 24 | } 25 | } 26 | 27 | func (dg *dhGroup) P() *big.Int { 28 | p := new(big.Int) 29 | p.Set(dg.p) 30 | return p 31 | } 32 | 33 | func (dg *dhGroup) G() *big.Int { 34 | g := new(big.Int) 35 | g.Set(dg.g) 36 | return g 37 | } 38 | 39 | // 生成本地公私钥 40 | func (dg *dhGroup) GeneratePrivateKey(randReader io.Reader) (key *DhKey, err error) { 41 | if randReader == nil { 42 | randReader = rand.Reader 43 | } 44 | // 0 < x < p 45 | x, err := rand.Int(randReader, dg.p) 46 | if err != nil { 47 | return 48 | } 49 | zero := big.NewInt(0) 50 | for x.Cmp(zero) == 0 { 51 | x, err = rand.Int(randReader, dg.p) 52 | if err != nil { 53 | return 54 | } 55 | } 56 | key = new(DhKey) 57 | key.x = x 58 | 59 | // y = g ^ x mod p 60 | key.y = new(big.Int).Exp(dg.g, x, dg.p) 61 | key.group = dg 62 | return 63 | } 64 | 65 | func (dg *dhGroup) ComputeKey(pubkey *DhKey, privkey *DhKey) (kye *DhKey, err error) { 66 | if dg.p == nil { 67 | err = errors.New("DH: invalid group") 68 | return 69 | } 70 | if pubkey.y == nil { 71 | err = errors.New("DH: invalid public key") 72 | return 73 | } 74 | if pubkey.y.Sign() <= 0 || pubkey.y.Cmp(dg.p) >= 0 { 75 | err = errors.New("DH parameter out of bounds") 76 | return 77 | } 78 | if privkey.x == nil { 79 | err = errors.New("DH: invalid private key") 80 | return 81 | } 82 | k := new(big.Int).Exp(pubkey.y, privkey.x, dg.p) 83 | key := new(DhKey) 84 | key.y = k 85 | key.group = dg 86 | return 87 | } 88 | -------------------------------------------------------------------------------- /security/zzb.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package security 7 | 8 | import "math/big" 9 | 10 | type DhKey struct { 11 | x *big.Int 12 | y *big.Int 13 | group *dhGroup 14 | } 15 | 16 | func newPublicKey(s []byte) *DhKey { 17 | key := new(DhKey) 18 | key.y = new(big.Int).SetBytes(s) 19 | return key 20 | } 21 | 22 | func (dk *DhKey) GetX() *big.Int { 23 | x := new(big.Int) 24 | x.Set(dk.x) 25 | return x 26 | } 27 | 28 | func (dk *DhKey) GetY() *big.Int { 29 | y := new(big.Int) 30 | y.Set(dk.y) 31 | return y 32 | } 33 | 34 | func (dk *DhKey) GetYBytes() []byte { 35 | if dk.y == nil { 36 | return nil 37 | } 38 | if dk.group != nil { 39 | blen := (dk.group.p.BitLen() + 7) / 8 40 | ret := make([]byte, blen) 41 | copyWithLeftPad(ret, dk.y.Bytes()) 42 | return ret 43 | } 44 | return dk.y.Bytes() 45 | } 46 | 47 | func (dk *DhKey) GetYString() string { 48 | if dk.y == nil { 49 | return "" 50 | } 51 | return dk.y.String() 52 | } 53 | 54 | func (dk *DhKey) IsPrivateKey() bool { 55 | return dk.x != nil 56 | } 57 | 58 | func copyWithLeftPad(dest, src []byte) { 59 | numPaddingBytes := len(dest) - len(src) 60 | for i := 0; i < numPaddingBytes; i++ { 61 | dest[i] = 0 62 | } 63 | copy(dest[:numPaddingBytes], src) 64 | } 65 | -------------------------------------------------------------------------------- /security/zzc.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | // go官方没有实现ecb加密模式 7 | package security 8 | 9 | import ( 10 | "crypto/cipher" 11 | ) 12 | 13 | type ecb struct { 14 | b cipher.Block 15 | blockSize int 16 | } 17 | 18 | func newECB(b cipher.Block) *ecb { 19 | return &ecb { 20 | b: b, 21 | blockSize: b.BlockSize(), 22 | } 23 | } 24 | 25 | type ecbEncrypter ecb 26 | 27 | func NewECBEncrypter(b cipher.Block) cipher.BlockMode { 28 | return (*ecbEncrypter)(newECB(b)) 29 | } 30 | 31 | func (x *ecbEncrypter) BlockSize() int { return x.blockSize } 32 | 33 | func (x *ecbEncrypter) CryptBlocks(dst, src []byte) { 34 | if len(src)%x.blockSize != 0 { 35 | panic("dm/security: input not full blocks") 36 | } 37 | if len(dst) < len(src) { 38 | panic("dm/security: output smaller than input") 39 | } 40 | if InexactOverlap(dst[:len(src)], src) { 41 | panic("dm/security: invalid buffer overlap") 42 | } 43 | for bs, be := 0, x.blockSize; bs < len(src); bs, be = bs + x.blockSize, be + x.blockSize { 44 | x.b.Encrypt(dst[bs:be], src[bs:be]) 45 | } 46 | } 47 | 48 | type ecbDecrypter ecb 49 | 50 | func NewECBDecrypter(b cipher.Block) cipher.BlockMode { 51 | return (*ecbDecrypter)(newECB(b)) 52 | } 53 | 54 | func (x *ecbDecrypter) BlockSize() int { return x.blockSize } 55 | 56 | func (x *ecbDecrypter) CryptBlocks(dst, src []byte) { 57 | if len(src)%x.blockSize != 0 { 58 | panic("dm/security: input not full blocks") 59 | } 60 | if len(dst) < len(src) { 61 | panic("dm/security: output smaller than input") 62 | } 63 | if InexactOverlap(dst[:len(src)], src) { 64 | panic("dm/security: invalid buffer overlap") 65 | } 66 | for bs, be := 0, x.blockSize; bs < len(src); bs, be = bs + x.blockSize, be + x.blockSize { 67 | x.b.Decrypt(dst[bs:be], src[bs:be]) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /security/zzd.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package security 7 | 8 | import ( 9 | "math/big" 10 | ) 11 | 12 | const ( 13 | DH_KEY_LENGTH int = 64 14 | /* 低7位用于保存分组加密算法中的工作模式 */ 15 | WORK_MODE_MASK int = 0x007f 16 | ECB_MODE int = 0x1 17 | CBC_MODE int = 0x2 18 | CFB_MODE int = 0x4 19 | OFB_MODE int = 0x8 20 | /* 高位保存加密算法 */ 21 | ALGO_MASK int = 0xff80 22 | DES int = 0x0080 23 | DES3 int = 0x0100 24 | AES128 int = 0x0200 25 | AES192 int = 0x0400 26 | AES256 int = 0x0800 27 | RC4 int = 0x1000 28 | MD5 int = 0x1100 29 | 30 | // 用户名密码加密算法 31 | DES_CFB int = 132 32 | // 消息加密摘要长度 33 | MD5_DIGEST_SIZE int = 16 34 | 35 | MIN_EXTERNAL_CIPHER_ID int = 5000 36 | ) 37 | 38 | var dhParaP = "C009D877BAF5FAF416B7F778E6115DCB90D65217DCC2F08A9DFCB5A192C593EBAB02929266B8DBFC2021039FDBD4B7FDE2B996E00008F57AE6EFB4ED3F17B6D3" 39 | var dhParaG = "5" 40 | var defaultIV = []byte{0x20, 0x21, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 41 | 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 42 | 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x20} 43 | var p *big.Int 44 | var g *big.Int 45 | 46 | func NewClientKeyPair() (key *DhKey, err error) { 47 | p, _ = new(big.Int).SetString(dhParaP, 16) 48 | g, _ = new(big.Int).SetString(dhParaG, 16) 49 | dhGroup := newDhGroup(p, g) 50 | key, err = dhGroup.GeneratePrivateKey(nil) 51 | if err != nil { 52 | return nil, err 53 | } 54 | return key, nil 55 | } 56 | 57 | func ComputeSessionKey(clientPrivKey *DhKey, serverPubKey []byte) []byte { 58 | serverKeyX := bytes2Bn(serverPubKey) 59 | clientPrivKeyX := clientPrivKey.GetX() 60 | sessionKeyBN := serverKeyX.Exp(serverKeyX, clientPrivKeyX, p) 61 | return Bn2Bytes(sessionKeyBN, 0) 62 | } 63 | 64 | func bytes2Bn(bnBytesSrc []byte) *big.Int { 65 | if bnBytesSrc == nil { 66 | return nil 67 | } 68 | if bnBytesSrc[0] == 0 { 69 | return new(big.Int).SetBytes(bnBytesSrc) 70 | } 71 | validBytesCount := len(bnBytesSrc) + 1 72 | bnBytesTo := make([]byte, validBytesCount) 73 | bnBytesTo[0] = 0 74 | copy(bnBytesTo[1:validBytesCount], bnBytesSrc) 75 | return new(big.Int).SetBytes(bnBytesTo) 76 | } 77 | 78 | func Bn2Bytes(bn *big.Int, bnLen int) []byte { 79 | var bnBytesSrc, bnBytesTemp, bnBytesTo []byte 80 | var leading_zero_count int 81 | validBytesCount := 0 82 | if bn == nil { 83 | return nil 84 | } 85 | bnBytesSrc = bn.Bytes() 86 | 87 | // 去除首位0 88 | if bnBytesSrc[0] != 0 { 89 | bnBytesTemp = bnBytesSrc 90 | validBytesCount = len(bnBytesTemp) 91 | } else { 92 | validBytesCount = len(bnBytesSrc) - 1 93 | bnBytesTemp = make([]byte, validBytesCount) 94 | copy(bnBytesTemp, bnBytesSrc[1:validBytesCount+1]) 95 | } 96 | 97 | if bnLen == 0 { 98 | leading_zero_count = 0 99 | } else { 100 | leading_zero_count = bnLen - validBytesCount 101 | } 102 | // 如果位数不足DH_KEY_LENGTH则在前面补0 103 | if leading_zero_count > 0 { 104 | bnBytesTo = make([]byte, DH_KEY_LENGTH) 105 | i := 0 106 | for i = 0; i < leading_zero_count; i++ { 107 | bnBytesTo[i] = 0 108 | } 109 | copy(bnBytesTo[i:i+validBytesCount], bnBytesTemp) 110 | } else { 111 | bnBytesTo = bnBytesTemp 112 | } 113 | return bnBytesTo 114 | } 115 | -------------------------------------------------------------------------------- /security/zze.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package security 7 | 8 | import ( 9 | "bytes" 10 | "crypto/aes" 11 | "crypto/cipher" 12 | "crypto/des" 13 | "crypto/md5" 14 | "crypto/rc4" 15 | "errors" 16 | "reflect" 17 | ) 18 | 19 | type SymmCipher struct { 20 | encryptCipher interface{} //cipher.BlockMode | cipher.Stream 21 | decryptCipher interface{} //cipher.BlockMode | cipher.Stream 22 | key []byte 23 | block cipher.Block // 分组加密算法 24 | algorithmType int 25 | workMode int 26 | needPadding bool 27 | } 28 | 29 | func NewSymmCipher(algorithmID int, key []byte) (SymmCipher, error) { 30 | var sc SymmCipher 31 | var err error 32 | sc.key = key 33 | sc.algorithmType = algorithmID & ALGO_MASK 34 | sc.workMode = algorithmID & WORK_MODE_MASK 35 | switch sc.algorithmType { 36 | case AES128: 37 | if sc.block, err = aes.NewCipher(key[:16]); err != nil { 38 | return sc, err 39 | } 40 | case AES192: 41 | if sc.block, err = aes.NewCipher(key[:24]); err != nil { 42 | return sc, err 43 | } 44 | case AES256: 45 | if sc.block, err = aes.NewCipher(key[:32]); err != nil { 46 | return sc, err 47 | } 48 | case DES: 49 | if sc.block, err = des.NewCipher(key[:8]); err != nil { 50 | return sc, err 51 | } 52 | case DES3: 53 | var tripleDESKey []byte 54 | tripleDESKey = append(tripleDESKey, key[:16]...) 55 | tripleDESKey = append(tripleDESKey, key[:8]...) 56 | if sc.block, err = des.NewTripleDESCipher(tripleDESKey); err != nil { 57 | return sc, err 58 | } 59 | case RC4: 60 | if sc.encryptCipher, err = rc4.NewCipher(key[:16]); err != nil { 61 | return sc, err 62 | } 63 | if sc.decryptCipher, err = rc4.NewCipher(key[:16]); err != nil { 64 | return sc, err 65 | } 66 | return sc, nil 67 | default: 68 | return sc, errors.New("invalidCipher") 69 | } 70 | blockSize := sc.block.BlockSize() 71 | if sc.encryptCipher, err = sc.getEncrypter(sc.workMode, sc.block, defaultIV[:blockSize]); err != nil { 72 | return sc, err 73 | } 74 | if sc.decryptCipher, err = sc.getDecrypter(sc.workMode, sc.block, defaultIV[:blockSize]); err != nil { 75 | return sc, err 76 | } 77 | return sc, nil 78 | } 79 | 80 | func (sc SymmCipher) Encrypt(plaintext []byte, genDigest bool) []byte { 81 | // 执行过加密后,IV值变了,需要重新初始化encryptCipher对象(因为没有类似resetIV的方法) 82 | if sc.algorithmType != RC4 { 83 | sc.encryptCipher, _ = sc.getEncrypter(sc.workMode, sc.block, defaultIV[:sc.block.BlockSize()]) 84 | } else { 85 | sc.encryptCipher, _ = rc4.NewCipher(sc.key[:16]) 86 | } 87 | // 填充 88 | var paddingtext = make([]byte, len(plaintext)) 89 | copy(paddingtext, plaintext) 90 | if sc.needPadding { 91 | paddingtext = pkcs5Padding(paddingtext) 92 | } 93 | 94 | ret := make([]byte, len(paddingtext)) 95 | 96 | if v, ok := sc.encryptCipher.(cipher.Stream); ok { 97 | v.XORKeyStream(ret, paddingtext) 98 | } else if v, ok := sc.encryptCipher.(cipher.BlockMode); ok { 99 | v.CryptBlocks(ret, paddingtext) 100 | } 101 | 102 | // md5摘要 103 | if genDigest { 104 | digest := md5.Sum(plaintext) 105 | encrypt := ret 106 | ret = make([]byte, len(encrypt)+len(digest)) 107 | copy(ret[:len(encrypt)], encrypt) 108 | copy(ret[len(encrypt):], digest[:]) 109 | } 110 | return ret 111 | } 112 | 113 | func (sc SymmCipher) Decrypt(ciphertext []byte, checkDigest bool) ([]byte, error) { 114 | // 执行过解密后,IV值变了,需要重新初始化decryptCipher对象(因为没有类似resetIV的方法) 115 | if sc.algorithmType != RC4 { 116 | sc.decryptCipher, _ = sc.getDecrypter(sc.workMode, sc.block, defaultIV[:sc.block.BlockSize()]) 117 | } else { 118 | sc.decryptCipher, _ = rc4.NewCipher(sc.key[:16]) 119 | } 120 | var ret []byte 121 | if checkDigest { 122 | var digest = ciphertext[len(ciphertext)-MD5_DIGEST_SIZE:] 123 | ret = ciphertext[:len(ciphertext)-MD5_DIGEST_SIZE] 124 | ret = sc.decrypt(ret) 125 | var msgDigest = md5.Sum(ret) 126 | if !reflect.DeepEqual(msgDigest[:], digest) { 127 | return nil, errors.New("Decrypt failed/Digest not match\n") 128 | } 129 | } else { 130 | ret = sc.decrypt(ciphertext) 131 | } 132 | return ret, nil 133 | } 134 | 135 | func (sc SymmCipher) decrypt(ciphertext []byte) []byte { 136 | ret := make([]byte, len(ciphertext)) 137 | if v, ok := sc.decryptCipher.(cipher.Stream); ok { 138 | v.XORKeyStream(ret, ciphertext) 139 | } else if v, ok := sc.decryptCipher.(cipher.BlockMode); ok { 140 | v.CryptBlocks(ret, ciphertext) 141 | } 142 | // 去除填充 143 | if sc.needPadding { 144 | ret = pkcs5UnPadding(ret) 145 | } 146 | return ret 147 | } 148 | 149 | func (sc *SymmCipher) getEncrypter(workMode int, block cipher.Block, iv []byte) (ret interface{}, err error) { 150 | switch workMode { 151 | case ECB_MODE: 152 | ret = NewECBEncrypter(block) 153 | sc.needPadding = true 154 | case CBC_MODE: 155 | ret = cipher.NewCBCEncrypter(block, iv) 156 | sc.needPadding = true 157 | case CFB_MODE: 158 | ret = cipher.NewCFBEncrypter(block, iv) 159 | sc.needPadding = false 160 | case OFB_MODE: 161 | ret = cipher.NewOFB(block, iv) 162 | sc.needPadding = false 163 | default: 164 | err = errors.New("invalidCipherMode") 165 | } 166 | return 167 | } 168 | 169 | func (sc *SymmCipher) getDecrypter(workMode int, block cipher.Block, iv []byte) (ret interface{}, err error) { 170 | switch workMode { 171 | case ECB_MODE: 172 | ret = NewECBDecrypter(block) 173 | sc.needPadding = true 174 | case CBC_MODE: 175 | ret = cipher.NewCBCDecrypter(block, iv) 176 | sc.needPadding = true 177 | case CFB_MODE: 178 | ret = cipher.NewCFBDecrypter(block, iv) 179 | sc.needPadding = false 180 | case OFB_MODE: 181 | ret = cipher.NewOFB(block, iv) 182 | sc.needPadding = false 183 | default: 184 | err = errors.New("invalidCipherMode") 185 | } 186 | return 187 | } 188 | 189 | 190 | // 补码 191 | func pkcs77Padding(ciphertext []byte, blocksize int) []byte { 192 | padding := blocksize - len(ciphertext)%blocksize 193 | padtext := bytes.Repeat([]byte{byte(padding)}, padding) 194 | return append(ciphertext, padtext...) 195 | } 196 | 197 | // 去码 198 | func pkcs7UnPadding(origData []byte) []byte { 199 | length := len(origData) 200 | unpadding := int(origData[length-1]) 201 | return origData[:length-unpadding] 202 | } 203 | 204 | // 补码 205 | func pkcs5Padding(ciphertext []byte) []byte { 206 | return pkcs77Padding(ciphertext, 8) 207 | } 208 | 209 | // 去码 210 | func pkcs5UnPadding(ciphertext []byte) []byte { 211 | return pkcs7UnPadding(ciphertext) 212 | } -------------------------------------------------------------------------------- /security/zzf.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package security 7 | 8 | import ( 9 | "crypto/md5" 10 | "errors" 11 | "fmt" 12 | "reflect" 13 | "unsafe" 14 | ) 15 | 16 | type ThirdPartCipher struct { 17 | encryptType int // 外部加密算法id 18 | encryptName string // 外部加密算法名称 19 | hashType int 20 | key []byte 21 | cipherCount int // 外部加密算法个数 22 | //innerId int // 外部加密算法内部id 23 | blockSize int // 分组块大小 24 | khSize int // key/hash大小 25 | } 26 | 27 | func NewThirdPartCipher(encryptType int, key []byte, cipherPath string, hashType int) (ThirdPartCipher, error) { 28 | var tpc = ThirdPartCipher{ 29 | encryptType: encryptType, 30 | key: key, 31 | hashType: hashType, 32 | cipherCount: -1, 33 | } 34 | var err error 35 | err = initThirdPartCipher(cipherPath) 36 | if err != nil { 37 | return tpc, err 38 | } 39 | tpc.getCount() 40 | tpc.getInfo() 41 | return tpc, nil 42 | } 43 | 44 | func (tpc *ThirdPartCipher) getCount() int { 45 | if tpc.cipherCount == -1 { 46 | tpc.cipherCount = cipherGetCount() 47 | } 48 | return tpc.cipherCount 49 | } 50 | 51 | func (tpc *ThirdPartCipher) getInfo() { 52 | var cipher_id, ty, blk_size, kh_size int 53 | //var strptr, _ = syscall.UTF16PtrFromString(tpc.encryptName) 54 | var strptr *uint16 = new(uint16) 55 | for i := 1; i <= tpc.getCount(); i++ { 56 | cipherGetInfo(uintptr(i), uintptr(unsafe.Pointer(&cipher_id)), uintptr(unsafe.Pointer(&strptr)), 57 | uintptr(unsafe.Pointer(&ty)), uintptr(unsafe.Pointer(&blk_size)), uintptr(unsafe.Pointer(&kh_size))) 58 | if tpc.encryptType == cipher_id { 59 | tpc.blockSize = blk_size 60 | tpc.khSize = kh_size 61 | tpc.encryptName = string(uintptr2bytes(uintptr(unsafe.Pointer(strptr)))) 62 | return 63 | } 64 | } 65 | panic(fmt.Sprintf("ThirdPartyCipher: cipher id:%d not found", tpc.encryptType)) 66 | } 67 | 68 | func (tpc ThirdPartCipher) Encrypt(plaintext []byte, genDigest bool) []byte { 69 | var tmp_para uintptr 70 | cipherEncryptInit(uintptr(tpc.encryptType), uintptr(unsafe.Pointer(&tpc.key[0])), uintptr(len(tpc.key)), tmp_para) 71 | 72 | ciphertextLen := cipherGetCipherTextSize(uintptr(tpc.encryptType), tmp_para, uintptr(len(plaintext))) 73 | 74 | ciphertext := make([]byte, ciphertextLen) 75 | ret := cipherEncrypt(uintptr(tpc.encryptType), tmp_para, uintptr(unsafe.Pointer(&plaintext[0])), uintptr(len(plaintext)), 76 | uintptr(unsafe.Pointer(&ciphertext[0])), uintptr(len(ciphertext))) 77 | ciphertext = ciphertext[:ret] 78 | 79 | cipherClean(uintptr(tpc.encryptType), tmp_para) 80 | // md5摘要 81 | if genDigest { 82 | digest := md5.Sum(plaintext) 83 | encrypt := ciphertext 84 | ciphertext = make([]byte, len(encrypt)+len(digest)) 85 | copy(ciphertext[:len(encrypt)], encrypt) 86 | copy(ciphertext[len(encrypt):], digest[:]) 87 | } 88 | return ciphertext 89 | } 90 | 91 | func (tpc ThirdPartCipher) Decrypt(ciphertext []byte, checkDigest bool) ([]byte, error) { 92 | var ret []byte 93 | if checkDigest { 94 | var digest = ciphertext[len(ciphertext)-MD5_DIGEST_SIZE:] 95 | ret = ciphertext[:len(ciphertext)-MD5_DIGEST_SIZE] 96 | ret = tpc.decrypt(ret) 97 | var msgDigest = md5.Sum(ret) 98 | if !reflect.DeepEqual(msgDigest[:], digest) { 99 | return nil, errors.New("Decrypt failed/Digest not match\n") 100 | } 101 | } else { 102 | ret = tpc.decrypt(ciphertext) 103 | } 104 | return ret, nil 105 | } 106 | 107 | func (tpc ThirdPartCipher) decrypt(ciphertext []byte) []byte { 108 | var tmp_para uintptr 109 | 110 | cipherDecryptInit(uintptr(tpc.encryptType), uintptr(unsafe.Pointer(&tpc.key[0])), uintptr(len(tpc.key)), tmp_para) 111 | 112 | plaintext := make([]byte, len(ciphertext)) 113 | ret := cipherDecrypt(uintptr(tpc.encryptType), tmp_para, uintptr(unsafe.Pointer(&ciphertext[0])), uintptr(len(ciphertext)), 114 | uintptr(unsafe.Pointer(&plaintext[0])), uintptr(len(plaintext))) 115 | plaintext = plaintext[:ret] 116 | 117 | cipherClean(uintptr(tpc.encryptType), tmp_para) 118 | return plaintext 119 | } 120 | 121 | func addBufSize(buf []byte, newCap int) []byte { 122 | newBuf := make([]byte, newCap) 123 | copy(newBuf, buf) 124 | return newBuf 125 | } 126 | 127 | func uintptr2bytes(p uintptr) []byte { 128 | buf := make([]byte, 64) 129 | i := 0 130 | for b := (*byte)(unsafe.Pointer(p)); *b != 0; i++ { 131 | if i > cap(buf) { 132 | buf = addBufSize(buf, i * 2) 133 | } 134 | buf[i] = *b 135 | // byte占1字节 136 | p ++ 137 | b = (*byte)(unsafe.Pointer(p)) 138 | } 139 | return buf[:i] 140 | } 141 | -------------------------------------------------------------------------------- /security/zzg_linux.go: -------------------------------------------------------------------------------- 1 | // +build linux 2 | 3 | /* 4 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 5 | * All rights reserved. 6 | */ 7 | 8 | package security 9 | 10 | import "plugin" 11 | 12 | var ( 13 | dmCipherEncryptSo *plugin.Plugin 14 | cipherGetCountProc plugin.Symbol 15 | cipherGetInfoProc plugin.Symbol 16 | cipherEncryptInitProc plugin.Symbol 17 | cipherGetCipherTextSizeProc plugin.Symbol 18 | cipherEncryptProc plugin.Symbol 19 | cipherCleanupProc plugin.Symbol 20 | cipherDecryptInitProc plugin.Symbol 21 | cipherDecryptProc plugin.Symbol 22 | ) 23 | 24 | func initThirdPartCipher(cipherPath string) (err error) { 25 | if dmCipherEncryptSo, err = plugin.Open(cipherPath); err != nil { 26 | return err 27 | } 28 | if cipherGetCountProc, err = dmCipherEncryptSo.Lookup("cipher_get_count"); err != nil { 29 | return err 30 | } 31 | if cipherGetInfoProc, err = dmCipherEncryptSo.Lookup("cipher_get_info"); err != nil { 32 | return err 33 | } 34 | if cipherEncryptInitProc, err = dmCipherEncryptSo.Lookup("cipher_encrypt_init"); err != nil { 35 | return err 36 | } 37 | if cipherGetCipherTextSizeProc, err = dmCipherEncryptSo.Lookup("cipher_get_cipher_text_size"); err != nil { 38 | return err 39 | } 40 | if cipherEncryptProc, err = dmCipherEncryptSo.Lookup("cipher_encrypt"); err != nil { 41 | return err 42 | } 43 | if cipherCleanupProc, err = dmCipherEncryptSo.Lookup("cipher_cleanup"); err != nil { 44 | return err 45 | } 46 | if cipherDecryptInitProc, err = dmCipherEncryptSo.Lookup("cipher_decrypt_init"); err != nil { 47 | return err 48 | } 49 | if cipherDecryptProc, err = dmCipherEncryptSo.Lookup("cipher_decrypt"); err != nil { 50 | return err 51 | } 52 | return nil 53 | } 54 | 55 | func cipherGetCount() int { 56 | ret := cipherGetCountProc.(func() interface{})() 57 | return ret.(int) 58 | } 59 | 60 | func cipherGetInfo(seqno, cipherId, cipherName, _type, blkSize, khSIze uintptr) { 61 | ret := cipherGetInfoProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(seqno, cipherId, cipherName, _type, blkSize, khSIze) 62 | if ret.(int) == 0 { 63 | panic("ThirdPartyCipher: call cipher_get_info failed") 64 | } 65 | } 66 | 67 | func cipherEncryptInit(cipherId, key, keySize, cipherPara uintptr) { 68 | ret := cipherEncryptInitProc.(func(uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, key, keySize, cipherPara) 69 | if ret.(int) == 0 { 70 | panic("ThirdPartyCipher: call cipher_encrypt_init failed") 71 | } 72 | } 73 | 74 | func cipherGetCipherTextSize(cipherId, cipherPara, plainTextSize uintptr) uintptr { 75 | ciphertextLen := cipherGetCipherTextSizeProc.(func(uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, plainTextSize) 76 | return ciphertextLen.(uintptr) 77 | } 78 | 79 | func cipherEncrypt(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize uintptr) uintptr { 80 | ret := cipherEncryptProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize) 81 | return ret.(uintptr) 82 | } 83 | 84 | func cipherClean(cipherId, cipherPara uintptr) { 85 | cipherEncryptProc.(func(uintptr, uintptr))(cipherId, cipherPara) 86 | } 87 | 88 | func cipherDecryptInit(cipherId, key, keySize, cipherPara uintptr) { 89 | ret := cipherDecryptInitProc.(func(uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, key, keySize, cipherPara) 90 | if ret.(int) == 0 { 91 | panic("ThirdPartyCipher: call cipher_decrypt_init failed") 92 | } 93 | } 94 | 95 | func cipherDecrypt(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize uintptr) uintptr { 96 | ret := cipherDecryptProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize) 97 | return ret.(uintptr) 98 | } 99 | -------------------------------------------------------------------------------- /security/zzg_mac.go: -------------------------------------------------------------------------------- 1 | // +build darwin 2 | 3 | /* 4 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 5 | * All rights reserved. 6 | */ 7 | 8 | package security 9 | 10 | import "plugin" 11 | 12 | var ( 13 | dmCipherEncryptSo *plugin.Plugin 14 | cipherGetCountProc plugin.Symbol 15 | cipherGetInfoProc plugin.Symbol 16 | cipherEncryptInitProc plugin.Symbol 17 | cipherGetCipherTextSizeProc plugin.Symbol 18 | cipherEncryptProc plugin.Symbol 19 | cipherCleanupProc plugin.Symbol 20 | cipherDecryptInitProc plugin.Symbol 21 | cipherDecryptProc plugin.Symbol 22 | ) 23 | 24 | func initThirdPartCipher(cipherPath string) (err error) { 25 | if dmCipherEncryptSo, err = plugin.Open(cipherPath); err != nil { 26 | return err 27 | } 28 | if cipherGetCountProc, err = dmCipherEncryptSo.Lookup("cipher_get_count"); err != nil { 29 | return err 30 | } 31 | if cipherGetInfoProc, err = dmCipherEncryptSo.Lookup("cipher_get_info"); err != nil { 32 | return err 33 | } 34 | if cipherEncryptInitProc, err = dmCipherEncryptSo.Lookup("cipher_encrypt_init"); err != nil { 35 | return err 36 | } 37 | if cipherGetCipherTextSizeProc, err = dmCipherEncryptSo.Lookup("cipher_get_cipher_text_size"); err != nil { 38 | return err 39 | } 40 | if cipherEncryptProc, err = dmCipherEncryptSo.Lookup("cipher_encrypt"); err != nil { 41 | return err 42 | } 43 | if cipherCleanupProc, err = dmCipherEncryptSo.Lookup("cipher_cleanup"); err != nil { 44 | return err 45 | } 46 | if cipherDecryptInitProc, err = dmCipherEncryptSo.Lookup("cipher_decrypt_init"); err != nil { 47 | return err 48 | } 49 | if cipherDecryptProc, err = dmCipherEncryptSo.Lookup("cipher_decrypt"); err != nil { 50 | return err 51 | } 52 | return nil 53 | } 54 | 55 | func cipherGetCount() int { 56 | ret := cipherGetCountProc.(func() interface{})() 57 | return ret.(int) 58 | } 59 | 60 | func cipherGetInfo(seqno, cipherId, cipherName, _type, blkSize, khSIze uintptr) { 61 | ret := cipherGetInfoProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(seqno, cipherId, cipherName, _type, blkSize, khSIze) 62 | if ret.(int) == 0 { 63 | panic("ThirdPartyCipher: call cipher_get_info failed") 64 | } 65 | } 66 | 67 | func cipherEncryptInit(cipherId, key, keySize, cipherPara uintptr) { 68 | ret := cipherEncryptInitProc.(func(uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, key, keySize, cipherPara) 69 | if ret.(int) == 0 { 70 | panic("ThirdPartyCipher: call cipher_encrypt_init failed") 71 | } 72 | } 73 | 74 | func cipherGetCipherTextSize(cipherId, cipherPara, plainTextSize uintptr) uintptr { 75 | ciphertextLen := cipherGetCipherTextSizeProc.(func(uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, plainTextSize) 76 | return ciphertextLen.(uintptr) 77 | } 78 | 79 | func cipherEncrypt(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize uintptr) uintptr { 80 | ret := cipherEncryptProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize) 81 | return ret.(uintptr) 82 | } 83 | 84 | func cipherClean(cipherId, cipherPara uintptr) { 85 | cipherEncryptProc.(func(uintptr, uintptr))(cipherId, cipherPara) 86 | } 87 | 88 | func cipherDecryptInit(cipherId, key, keySize, cipherPara uintptr) { 89 | ret := cipherDecryptInitProc.(func(uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, key, keySize, cipherPara) 90 | if ret.(int) == 0 { 91 | panic("ThirdPartyCipher: call cipher_decrypt_init failed") 92 | } 93 | } 94 | 95 | func cipherDecrypt(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize uintptr) uintptr { 96 | ret := cipherDecryptProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize) 97 | return ret.(uintptr) 98 | } 99 | -------------------------------------------------------------------------------- /security/zzh_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | /* 4 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 5 | * All rights reserved. 6 | */ 7 | 8 | package security 9 | 10 | import ( 11 | "syscall" 12 | ) 13 | 14 | var ( 15 | dmCipherEncryptDLL *syscall.LazyDLL 16 | cipherGetCountProc *syscall.LazyProc 17 | cipherGetInfoProc *syscall.LazyProc 18 | cipherEncryptInitProc *syscall.LazyProc 19 | cipherGetCipherTextSizeProc *syscall.LazyProc 20 | cipherEncryptProc *syscall.LazyProc 21 | cipherCleanupProc *syscall.LazyProc 22 | cipherDecryptInitProc *syscall.LazyProc 23 | cipherDecryptProc *syscall.LazyProc 24 | ) 25 | 26 | func initThirdPartCipher(cipherPath string) error { 27 | dmCipherEncryptDLL = syscall.NewLazyDLL(cipherPath) 28 | if err := dmCipherEncryptDLL.Load(); err != nil { 29 | return err 30 | } 31 | cipherGetCountProc = dmCipherEncryptDLL.NewProc("cipher_get_count") 32 | cipherGetInfoProc = dmCipherEncryptDLL.NewProc("cipher_get_info") 33 | cipherEncryptInitProc = dmCipherEncryptDLL.NewProc("cipher_encrypt_init") 34 | cipherGetCipherTextSizeProc = dmCipherEncryptDLL.NewProc("cipher_get_cipher_text_size") 35 | cipherEncryptProc = dmCipherEncryptDLL.NewProc("cipher_encrypt") 36 | cipherCleanupProc = dmCipherEncryptDLL.NewProc("cipher_cleanup") 37 | cipherDecryptInitProc = dmCipherEncryptDLL.NewProc("cipher_decrypt_init") 38 | cipherDecryptProc = dmCipherEncryptDLL.NewProc("cipher_decrypt") 39 | return nil 40 | } 41 | 42 | func cipherGetCount() int { 43 | ret, _, _ := cipherGetCountProc.Call() 44 | return int(ret) 45 | } 46 | 47 | func cipherGetInfo(seqno, cipherId, cipherName, _type, blkSize, khSIze uintptr) { 48 | ret, _, _ := cipherGetInfoProc.Call(seqno, cipherId, cipherName, _type, blkSize, khSIze) 49 | if ret == 0 { 50 | panic("ThirdPartyCipher: call cipher_get_info failed") 51 | } 52 | } 53 | 54 | func cipherEncryptInit(cipherId, key, keySize, cipherPara uintptr) { 55 | ret, _, _ := cipherEncryptInitProc.Call(cipherId, key, keySize, cipherPara) 56 | if ret == 0 { 57 | panic("ThirdPartyCipher: call cipher_encrypt_init failed") 58 | } 59 | } 60 | 61 | func cipherGetCipherTextSize(cipherId, cipherPara, plainTextSize uintptr) uintptr { 62 | ciphertextLen, _, _ := cipherGetCipherTextSizeProc.Call(cipherId, cipherPara, plainTextSize) 63 | return ciphertextLen 64 | } 65 | 66 | func cipherEncrypt(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize uintptr) uintptr { 67 | ret, _, _ := cipherEncryptProc.Call(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize) 68 | return ret 69 | } 70 | 71 | func cipherClean(cipherId, cipherPara uintptr) { 72 | _, _, _ = cipherCleanupProc.Call(cipherId, cipherPara) 73 | } 74 | 75 | func cipherDecryptInit(cipherId, key, keySize, cipherPara uintptr) { 76 | ret, _, _ := cipherDecryptInitProc.Call(cipherId, key, keySize, cipherPara) 77 | if ret == 0 { 78 | panic("ThirdPartyCipher: call cipher_decrypt_init failed") 79 | } 80 | } 81 | 82 | func cipherDecrypt(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize uintptr) uintptr { 83 | ret, _, _ := cipherDecryptProc.Call(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize) 84 | return ret 85 | } 86 | -------------------------------------------------------------------------------- /security/zzi.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package security 7 | 8 | import ( 9 | "crypto/tls" 10 | "errors" 11 | "flag" 12 | "net" 13 | "os" 14 | ) 15 | 16 | var dmHome = flag.String("DM_HOME", "", "Where DMDB installed") 17 | 18 | func NewTLSFromTCP(conn *net.TCPConn, sslCertPath string, sslKeyPath string, user string) (*tls.Conn, error) { 19 | if sslCertPath == "" && sslKeyPath == "" { 20 | flag.Parse() 21 | separator := string(os.PathSeparator) 22 | if *dmHome != "" { 23 | sslCertPath = *dmHome + separator + "bin" + separator + "client_ssl" + separator + 24 | user + separator + "client-cert.pem" 25 | sslKeyPath = *dmHome + separator + "bin" + separator + "client_ssl" + separator + 26 | user + separator + "client-key.pem" 27 | } else { 28 | return nil, errors.New("sslCertPath and sslKeyPath can not be empty!") 29 | } 30 | } 31 | cer, err := tls.LoadX509KeyPair(sslCertPath, sslKeyPath) 32 | if err != nil { 33 | return nil, err 34 | } 35 | conf := &tls.Config{ 36 | InsecureSkipVerify: true, 37 | Certificates: []tls.Certificate{cer}, 38 | } 39 | tlsConn := tls.Client(conn, conf) 40 | if err := tlsConn.Handshake(); err != nil { 41 | return nil, err 42 | } 43 | return tlsConn, nil 44 | } -------------------------------------------------------------------------------- /util/zzq.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package util 7 | 8 | func Split(s string, sep string) []string { 9 | var foot = make([]int, len(s)) // 足够的元素个数 10 | var count, sLen, sepLen = 0, len(s), len(sep) 11 | for i := 0; i < sLen; i++ { 12 | // 处理 s == “-9999-1" && seperators == "-"情况 13 | if i == 0 && sLen >= sepLen { 14 | if s[0:sepLen] == sep { 15 | i += sepLen - 1 16 | continue 17 | } 18 | } 19 | for j := 0; j < sepLen; j++ { 20 | if s[i] == sep[j] { 21 | foot[count] = i 22 | count++ 23 | break 24 | } 25 | } 26 | } 27 | var ret = make([]string, count+1) 28 | if count == 0 { 29 | ret[0] = s 30 | return ret 31 | } 32 | ret[0] = s[0:foot[0]] 33 | for i := 1; i < count; i++ { 34 | ret[i] = s[foot[i-1]+1 : foot[i]] 35 | } 36 | ret[count] = s[foot[count-1]+1:] 37 | return ret 38 | } 39 | -------------------------------------------------------------------------------- /util/zzr.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package util 7 | 8 | import ( 9 | "go/build" 10 | "os" 11 | "runtime" 12 | "strings" 13 | ) 14 | 15 | const ( 16 | PathSeparator = string(os.PathSeparator) 17 | PathListSeparator = string(os.PathListSeparator) 18 | ) 19 | 20 | var ( 21 | goRoot = build.Default.GOROOT 22 | goPath = build.Default.GOPATH //获取实际编译时的GOPATH值 23 | ) 24 | 25 | type fileUtil struct { 26 | } 27 | 28 | var FileUtil = &fileUtil{} 29 | 30 | func (fileUtil *fileUtil) Exists(path string) bool { 31 | if _, err := os.Stat(path); !os.IsNotExist(err) { 32 | return true 33 | } 34 | return false 35 | } 36 | 37 | func (fileUtil *fileUtil) Search(relativePath string) (path string) { 38 | if strings.Contains(runtime.GOOS, "windows") { 39 | relativePath = strings.ReplaceAll(relativePath, "/", "\\") 40 | } 41 | 42 | if fileUtil.Exists(goPath) { 43 | for _, s := range strings.Split(goPath, PathListSeparator) { 44 | path = s + PathSeparator + "src" + PathSeparator + relativePath 45 | if fileUtil.Exists(path) { 46 | return path 47 | } 48 | } 49 | } 50 | 51 | if fileUtil.Exists(goPath) { 52 | for _, s := range strings.Split(goPath, PathListSeparator) { 53 | path = s + PathSeparator + "pkg" + PathSeparator + relativePath 54 | if fileUtil.Exists(path) { 55 | return path 56 | } 57 | } 58 | } 59 | 60 | //if workDir, _ := os.Getwd(); fileUtil.Exists(workDir) { 61 | // path = workDir + PathSeparator + "src" + PathSeparator + relativePath 62 | // if fileUtil.Exists(path) { 63 | // return path 64 | // } 65 | //} 66 | 67 | //if fileUtil.Exists(goRoot) { 68 | // path = goRoot + PathSeparator + "src" + PathSeparator + relativePath 69 | // if fileUtil.Exists(path) { 70 | // return path 71 | // } 72 | //} 73 | 74 | return "" 75 | } 76 | -------------------------------------------------------------------------------- /util/zzs.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | package util 6 | 7 | const ( 8 | LINE_SEPARATOR = "\n" 9 | ) 10 | 11 | func SliceEquals(src []byte, dest []byte) bool { 12 | if len(src) != len(dest) { 13 | return false 14 | } 15 | 16 | for i, _ := range src { 17 | if src[i] != dest[i] { 18 | return false 19 | } 20 | } 21 | 22 | return true 23 | } 24 | 25 | // 获取两个数的最大公约数,由调用者确保m、n>=0;如果m或n为0,返回1 26 | func GCD(m int32, n int32) int32 { 27 | if m == 0 || n == 0 { 28 | return 1 29 | } 30 | r := m % n 31 | m = n 32 | n = r 33 | if r == 0 { 34 | return m 35 | } else { 36 | return GCD(m, n) 37 | } 38 | } 39 | 40 | // 返回切片中所有数的累加值 41 | func Sum(arr []int32) int32 { 42 | var sum int32 = 0 43 | for _, i := range arr { 44 | sum += i 45 | } 46 | return sum 47 | } 48 | -------------------------------------------------------------------------------- /util/zzt.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package util 7 | 8 | import ( 9 | "bytes" 10 | "runtime" 11 | "strings" 12 | "time" 13 | "unicode" 14 | ) 15 | 16 | type stringutil struct{} 17 | 18 | var StringUtil = &stringutil{} 19 | 20 | /*----------------------------------------------------*/ 21 | func (StringUtil *stringutil) LineSeparator() string { 22 | var lineSeparator string 23 | if strings.Contains(runtime.GOOS, "windos") { 24 | lineSeparator = "\r\n" 25 | } else if strings.Contains(runtime.GOOS, "mac") { 26 | lineSeparator = "\r" 27 | } else { 28 | lineSeparator = "\n" 29 | } 30 | 31 | return lineSeparator 32 | } 33 | 34 | func (StringUtil *stringutil) Equals(str1 string, str2 string) bool { 35 | return str1 == str2 36 | } 37 | 38 | func (StringUtil *stringutil) EqualsIgnoreCase(str1 string, str2 string) bool { 39 | return strings.ToUpper(str1) == strings.ToUpper(str2) 40 | } 41 | 42 | func (StringUtil *stringutil) StartsWith(s string, subStr string) bool { 43 | return strings.Index(s, subStr) == 0 44 | } 45 | 46 | func (StringUtil *stringutil) StartWithIgnoreCase(s string, subStr string) bool { 47 | return strings.HasPrefix(strings.ToLower(s), strings.ToLower(subStr)) 48 | } 49 | 50 | func (StringUtil *stringutil) EndsWith(s string, subStr string) bool { 51 | return strings.LastIndex(s, subStr) == len(s)-1 52 | } 53 | 54 | func (StringUtil *stringutil) IsDigit(str string) bool { 55 | if str == "" { 56 | return false 57 | } 58 | sz := len(str) 59 | for i := 0; i < sz; i++ { 60 | if unicode.IsDigit(rune(str[i])) { 61 | continue 62 | } else { 63 | return false 64 | } 65 | } 66 | return true 67 | } 68 | 69 | func (StringUtil *stringutil) FormatDir(dir string) string { 70 | dir = strings.TrimSpace(dir) 71 | if dir != "" { 72 | if !StringUtil.EndsWith(dir, PathSeparator) { 73 | dir += PathSeparator 74 | } 75 | } 76 | return dir 77 | } 78 | 79 | func (StringUtil *stringutil) HexStringToBytes(s string) []byte { 80 | str := s 81 | 82 | bs := make([]byte, 0) 83 | flag := false 84 | 85 | str = strings.TrimSpace(str) 86 | if strings.Index(str, "0x") == 0 || strings.Index(str, "0X") == 0 { 87 | str = str[2:] 88 | } 89 | 90 | if len(str) == 0 { 91 | return bs 92 | } 93 | 94 | var bsChr []byte 95 | l := len(str) 96 | 97 | if l%2 == 0 { 98 | bsChr = []byte(str) 99 | } else { 100 | l += 1 101 | bsChr = make([]byte, l) 102 | bsChr[0] = '0' 103 | for i := 0; i < l-1; i++ { 104 | bsChr[i+1] = str[i] 105 | } 106 | } 107 | 108 | bs = make([]byte, l/2) 109 | 110 | pos := 0 111 | for i := 0; i < len(bsChr); i += 2 { 112 | bt := convertHex(bsChr[i]) 113 | bt2 := convertHex(bsChr[i+1]) 114 | if int(bt) == 0xff || int(bt2) == 0xff { 115 | flag = true 116 | break 117 | } 118 | 119 | bs[pos] = byte(bt*16 + bt2) 120 | pos++ 121 | } 122 | 123 | if flag { 124 | bs = ([]byte)(str) 125 | } 126 | 127 | return bs 128 | } 129 | 130 | func convertHex(chr byte) byte { 131 | if chr >= '0' && chr <= '9' { 132 | return chr - '0' 133 | } else if chr >= 'a' && chr <= 'f' { 134 | return chr - 'a' + 10 135 | } else if chr >= 'A' && chr <= 'F' { 136 | return chr - 'A' + 10 137 | } else { 138 | return 0xff 139 | } 140 | } 141 | 142 | func (StringUtil *stringutil) BytesToHexString(bs []byte, pre bool) string { 143 | if bs == nil { 144 | return "" 145 | } 146 | if len(bs) == 0 { 147 | return "" 148 | } 149 | 150 | hexDigits := "0123456789ABCDEF" 151 | ret := new(strings.Builder) 152 | for _, b := range bs { 153 | ret.WriteByte(hexDigits[0x0F&(b>>4)]) 154 | ret.WriteByte(hexDigits[0x0F&b]) 155 | } 156 | if pre { 157 | return "0x" + ret.String() 158 | } 159 | return ret.String() 160 | } 161 | 162 | func (StringUtil *stringutil) ProcessSingleQuoteOfName(name string) string { 163 | return StringUtil.processQuoteOfName(name, "'") 164 | } 165 | 166 | func (StringUtil *stringutil) ProcessDoubleQuoteOfName(name string) string { 167 | return StringUtil.processQuoteOfName(name, "\"") 168 | } 169 | 170 | func (StringUtil *stringutil) processQuoteOfName(name string, quote string) string { 171 | if quote == "" || name == "" { 172 | return name 173 | } 174 | 175 | temp := name 176 | result := bytes.NewBufferString("") 177 | index := -1 178 | quetoLength := len(quote) 179 | index = strings.Index(temp, quote) 180 | for index != -1 { 181 | result.WriteString(temp[:index+quetoLength]) 182 | result.WriteString(quote) 183 | temp = temp[index+quetoLength:] 184 | index = strings.Index(temp, quote) 185 | } 186 | result.WriteString(temp) 187 | return result.String() 188 | } 189 | 190 | func (StringUtil *stringutil) FormatTime() string { 191 | return time.Now().Format("2006-01-02 15:04:05") 192 | } 193 | 194 | func (StringUtil *stringutil) SubstringBetween(str string, open string, close string) string { 195 | if str == "" { 196 | return "" 197 | } 198 | 199 | iopen := -1 200 | if open != "" { 201 | iopen = strings.Index(str, open) 202 | } 203 | 204 | iclose := -1 205 | if close != "" { 206 | iclose = strings.LastIndex(str, close) 207 | } 208 | 209 | if iopen == -1 && iclose == -1 { 210 | return "" 211 | } else if iopen == -1 { 212 | return str[0:iclose] 213 | } else if iclose == -1 { 214 | return str[iopen:] 215 | } else { 216 | return str[iopen:iclose] 217 | } 218 | } 219 | -------------------------------------------------------------------------------- /v.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package dm 7 | 8 | type DmStruct struct { 9 | TypeData 10 | m_strctDesc *StructDescriptor // 结构体的描述信息 11 | 12 | m_attribs []TypeData // 各属性值 13 | 14 | m_objCount int // 一个数组项中存在对象类型的个数(class、动态数组) 15 | 16 | m_strCount int // 一个数组项中存在字符串类型的个数 17 | 18 | typeName string 19 | 20 | elements []interface{} 21 | } 22 | 23 | func newDmStruct(typeName string, elements []interface{}) *DmStruct { 24 | ds := new(DmStruct) 25 | ds.typeName = typeName 26 | ds.elements = elements 27 | return ds 28 | } 29 | 30 | func (ds *DmStruct) create(dc *Connection) (*DmStruct, error) { 31 | desc, err := newStructDescriptor(ds.typeName, dc) 32 | if err != nil { 33 | return nil, err 34 | } 35 | return ds.createByStructDescriptor(desc, dc) 36 | } 37 | 38 | func newDmStructByTypeData(atData []TypeData, desc *TypeDescriptor) *DmStruct { 39 | ds := new(DmStruct) 40 | ds.initTypeData() 41 | ds.m_strctDesc = newStructDescriptorByTypeDescriptor(desc) 42 | ds.m_attribs = atData 43 | return ds 44 | } 45 | 46 | func (dest *DmStruct) Scan(src interface{}) error { 47 | switch src := src.(type) { 48 | case nil: 49 | *dest = *new(DmStruct) 50 | return nil 51 | case *DmStruct: 52 | *dest = *src 53 | return nil 54 | default: 55 | return UNSUPPORTED_SCAN 56 | } 57 | } 58 | 59 | func (ds *DmStruct) getAttribsTypeData() []TypeData { 60 | return ds.m_attribs 61 | } 62 | 63 | func (ds *DmStruct) createByStructDescriptor(desc *StructDescriptor, conn *Connection) (*DmStruct, error) { 64 | ds.initTypeData() 65 | 66 | if nil == desc { 67 | return nil, ECGO_INVALID_PARAMETER_VALUE.throw() 68 | } 69 | 70 | ds.m_strctDesc = desc 71 | if nil == ds.elements { 72 | ds.m_attribs = make([]TypeData, desc.getSize()) 73 | } else { 74 | if desc.getSize() != len(ds.elements) && desc.getObjId() != 4 { 75 | return nil, ECGO_STRUCT_MEM_NOT_MATCH.throw() 76 | } 77 | var err error 78 | ds.m_attribs, err = TypeDataSV.toStruct(ds.elements, ds.m_strctDesc.m_typeDesc) 79 | if err != nil { 80 | return nil, err 81 | } 82 | } 83 | 84 | return ds, nil 85 | } 86 | 87 | func (ds *DmStruct) getSQLTypeName() (string, error) { 88 | return ds.m_strctDesc.m_typeDesc.getFulName() 89 | } 90 | 91 | func (ds *DmStruct) getAttributes() ([]interface{}, error) { 92 | return TypeDataSV.toJavaArrayByDmStruct(ds) 93 | } 94 | 95 | func (ds *DmStruct) checkCol(col int) error { 96 | if col < 1 || col > len(ds.m_attribs) { 97 | return ECGO_INVALID_SEQUENCE_NUMBER.throw() 98 | } 99 | return nil 100 | } 101 | 102 | // 获取指定索引的成员变量值,以TypeData的形式给出,col 1 based 103 | func (ds *DmStruct) getAttrValue(col int) (*TypeData, error) { 104 | err := ds.checkCol(col) 105 | if err != nil { 106 | return nil, err 107 | } 108 | return &ds.m_attribs[col-1], nil 109 | } 110 | -------------------------------------------------------------------------------- /w.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package dm 7 | 8 | import ( 9 | "strings" 10 | "time" 11 | ) 12 | 13 | const ( 14 | Seconds_1900_1970 = 2209017600 15 | 16 | OFFSET_YEAR = 0 17 | 18 | OFFSET_MONTH = 1 19 | 20 | OFFSET_DAY = 2 21 | 22 | OFFSET_HOUR = 3 23 | 24 | OFFSET_MINUTE = 4 25 | 26 | OFFSET_SECOND = 5 27 | 28 | OFFSET_MILLISECOND = 6 29 | 30 | OFFSET_TIMEZONE = 7 31 | 32 | DT_LEN = 8 33 | 34 | INVALID_VALUE = int(INT32_MIN) 35 | ) 36 | 37 | type DmTimestamp struct { 38 | dt []int 39 | dtype int 40 | scale int 41 | oracleFormatPattern string 42 | oracleDateLanguage int 43 | } 44 | 45 | func newDmTimestampFromDt(dt []int, dtype int, scale int) *DmTimestamp { 46 | dmts := new(DmTimestamp) 47 | dmts.dt = dt 48 | dmts.dtype = dtype 49 | dmts.scale = scale 50 | return dmts 51 | } 52 | 53 | func newDmTimestampFromBytes(bytes []byte, column column, conn *Connection) *DmTimestamp { 54 | dmts := new(DmTimestamp) 55 | dmts.dt = decode(bytes, column.isBdta, int(column.colType), int(column.scale), int(conn.dmConnector.localTimezone), int(conn.DbTimezone)) 56 | 57 | if isLocalTimeZone(int(column.colType), int(column.scale)) { 58 | dmts.scale = getLocalTimeZoneScale(int(column.colType), int(column.scale)) 59 | } else { 60 | dmts.scale = int(column.scale) 61 | } 62 | 63 | dmts.dtype = int(column.colType) 64 | dmts.scale = int(column.scale) 65 | dmts.oracleDateLanguage = int(conn.OracleDateLanguage) 66 | switch column.colType { 67 | case DATE: 68 | dmts.oracleFormatPattern = conn.FormatDate 69 | case TIME: 70 | dmts.oracleFormatPattern = conn.FormatTime 71 | case TIME_TZ: 72 | dmts.oracleFormatPattern = conn.FormatTimeTZ 73 | case DATETIME: 74 | dmts.oracleFormatPattern = conn.FormatTimestamp 75 | case DATETIME_TZ: 76 | dmts.oracleFormatPattern = conn.FormatTimestampTZ 77 | } 78 | return dmts 79 | } 80 | 81 | func NewDmTimestampFromString(str string) (*DmTimestamp, error) { 82 | dt := make([]int, DT_LEN) 83 | dtype, err := toDTFromString(strings.TrimSpace(str), dt) 84 | if err != nil { 85 | return nil, err 86 | } 87 | 88 | if dtype == DATE { 89 | return newDmTimestampFromDt(dt, dtype, 0), nil 90 | } 91 | return newDmTimestampFromDt(dt, dtype, 6), nil 92 | } 93 | 94 | func NewDmTimestampFromTime(time time.Time) *DmTimestamp { 95 | dt := toDTFromTime(time) 96 | return newDmTimestampFromDt(dt, DATETIME, 6) 97 | } 98 | 99 | func (dmTimestamp *DmTimestamp) ToTime() time.Time { 100 | return toTimeFromDT(dmTimestamp.dt, 0) 101 | } 102 | 103 | // 获取年月日时分秒毫秒时区 104 | func (dmTimestamp *DmTimestamp) GetDt() []int { 105 | return dmTimestamp.dt 106 | } 107 | 108 | func (dmTimestamp *DmTimestamp) CompareTo(ts DmTimestamp) int { 109 | if dmTimestamp.ToTime().Equal(ts.ToTime()) { 110 | return 0 111 | } else if dmTimestamp.ToTime().Before(ts.ToTime()) { 112 | return -1 113 | } else { 114 | return 1 115 | } 116 | } 117 | 118 | func (dmTimestamp *DmTimestamp) String() string { 119 | if dmTimestamp.oracleFormatPattern != "" { 120 | return dtToStringByOracleFormat(dmTimestamp.dt, dmTimestamp.oracleFormatPattern, dmTimestamp.oracleDateLanguage) 121 | } 122 | return dtToString(dmTimestamp.dt, dmTimestamp.dtype, dmTimestamp.scale) 123 | } 124 | 125 | func (dest *DmTimestamp) Scan(src interface{}) error { 126 | if dest == nil { 127 | return ECGO_STORE_IN_NIL_POINTER.throw() 128 | } 129 | switch src := src.(type) { 130 | case nil: 131 | *dest = *new(DmTimestamp) 132 | return nil 133 | case *DmTimestamp: 134 | *dest = *src 135 | return nil 136 | case time.Time: 137 | ret := NewDmTimestampFromTime(src) 138 | *dest = *ret 139 | return nil 140 | default: 141 | return UNSUPPORTED_SCAN 142 | } 143 | } 144 | 145 | func (dmTimestamp *DmTimestamp) toBytes() ([]byte, error) { 146 | return encode(dmTimestamp.dt, dmTimestamp.dtype, dmTimestamp.scale, dmTimestamp.dt[OFFSET_TIMEZONE]) 147 | } 148 | 149 | /** 150 | * 获取当前对象的年月日时分秒,如果原来没有decode会先decode; 151 | */ 152 | func (dmTimestamp *DmTimestamp) getDt() []int { 153 | return dmTimestamp.dt 154 | } 155 | 156 | func (dmTimestamp *DmTimestamp) getTime() int64 { 157 | sec := toTimeFromDT(dmTimestamp.dt, 0).Unix() 158 | return sec + int64(dmTimestamp.dt[OFFSET_MILLISECOND]) 159 | } 160 | 161 | func (dmTimestamp *DmTimestamp) setTime(time int64) { 162 | timeInMillis := (time / 1000) * 1000 163 | nanos := (int64)((time % 1000) * 1000000) 164 | if nanos < 0 { 165 | nanos = 1000000000 + nanos 166 | timeInMillis = (((time / 1000) - 1) * 1000) 167 | } 168 | dmTimestamp.dt = toDTFromUnix(timeInMillis, nanos) 169 | } 170 | 171 | func (dmTimestamp *DmTimestamp) setTimezone(tz int) error { 172 | // DM中合法的时区取值范围为-12:59至+14:00 173 | if tz <= -13*60 || tz > 14*60 { 174 | return ECGO_INVALID_DATETIME_FORMAT.throw() 175 | } 176 | dmTimestamp.dt[OFFSET_TIMEZONE] = tz 177 | return nil 178 | } 179 | 180 | func (dmTimestamp *DmTimestamp) getNano() int64 { 181 | return int64(dmTimestamp.dt[OFFSET_MILLISECOND] * 1000) 182 | } 183 | 184 | func (dmTimestamp *DmTimestamp) setNano(nano int64) { 185 | dmTimestamp.dt[OFFSET_MILLISECOND] = (int)(nano / 1000) 186 | } 187 | 188 | func (dmTimestamp *DmTimestamp) string() string { 189 | if dmTimestamp.oracleFormatPattern != "" { 190 | return dtToStringByOracleFormat(dmTimestamp.dt, dmTimestamp.oracleFormatPattern, dmTimestamp.oracleDateLanguage) 191 | } 192 | return dtToString(dmTimestamp.dt, dmTimestamp.dtype, dmTimestamp.scale) 193 | } 194 | -------------------------------------------------------------------------------- /y.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package dm 7 | 8 | import ( 9 | "bytes" 10 | "math/rand" 11 | "sync" 12 | "time" 13 | 14 | "github.com/gotomicro/dmgo/util" 15 | ) 16 | 17 | /** 18 | * dm_svc.conf中配置的服务名对应的一组实例, 以及相关属性和状态信息 19 | * 20 | * 需求: 21 | * 1. 连接均匀分布在各个节点上 22 | * 2. loginMode,loginStatus匹配 23 | * 3. 连接异常节点比较耗时,在DB列表中包含异常节点时异常连接尽量靠后,减少对建连接速度的影响 24 | * 25 | * 26 | * DB 连接顺序: 27 | * 1. well distribution,每次连接都从列表的下一个节点开始 28 | * 2. 用DB sort值按从大到小排序,sort为一个四位数XXXX,个位--serverStatus,十位--serverMode,共 有三种模式,最优先的 *100, 次优先的*10 29 | */ 30 | type epGroup struct { 31 | name string 32 | epList []*ep 33 | props *Properties 34 | epStartPos int32 // wellDistribute 起始位置 35 | lock sync.Mutex 36 | } 37 | 38 | func newEPGroup(name string, serverList []*ep) *epGroup { 39 | g := new(epGroup) 40 | g.name = name 41 | g.epList = serverList 42 | if serverList == nil || len(serverList) == 0 { 43 | g.epStartPos = -1 44 | } else { 45 | // 保证进程间均衡,起始位置采用随机值 46 | g.epStartPos = rand.Int31n(int32(len(serverList))) - 1 47 | } 48 | return g 49 | } 50 | 51 | func (g *epGroup) connect(connector *Connector) (*Connection, error) { 52 | var dbSelector = g.getEPSelector(connector) 53 | var ex error = nil 54 | // 如果配置了loginMode的主、备等优先策略,而未找到最高优先级的节点时持续循环switchtimes次,如果最终还是没有找到最高优先级则选择次优先级的 55 | // 如果只有一个节点,一轮即可决定是否连接;多个节点时保证switchTimes轮尝试,最后一轮决定用哪个节点(由于节点已经按照模式优先级排序,最后一轮理论上就是连第一个节点) 56 | var cycleCount int32 57 | if len(g.epList) == 1 { 58 | cycleCount = 1 59 | } else { 60 | cycleCount = connector.switchTimes + 1 61 | } 62 | for i := int32(0); i < cycleCount; i++ { 63 | // 循环了一遍,如果没有符合要求的, 重新排序, 再尝试连接 64 | conn, err := g.traverseServerList(connector, dbSelector, i == 0, i == cycleCount-1) 65 | if err != nil { 66 | ex = err 67 | time.Sleep(time.Duration(connector.switchInterval) * time.Millisecond) 68 | continue 69 | } 70 | return conn, nil 71 | } 72 | return nil, ex 73 | } 74 | 75 | func (g *epGroup) getEPSelector(connector *Connector) *epSelector { 76 | if connector.epSelector == TYPE_HEAD_FIRST { 77 | return newEPSelector(g.epList) 78 | } else { 79 | serverCount := int32(len(g.epList)) 80 | sortEPs := make([]*ep, serverCount) 81 | g.lock.Lock() 82 | defer g.lock.Unlock() 83 | g.epStartPos = (g.epStartPos + 1) % serverCount 84 | for i := int32(0); i < serverCount; i++ { 85 | sortEPs[i] = g.epList[(i+g.epStartPos)%serverCount] 86 | } 87 | return newEPSelector(sortEPs) 88 | } 89 | } 90 | 91 | /** 92 | * 从指定编号开始,遍历一遍服务名中的ip列表,只连接指定类型(主机或备机)的ip 93 | * @param servers 94 | * @param checkTime 95 | * 96 | * @exception 97 | * DBError.ECJDBC_INVALID_SERVER_MODE 有站点的模式不匹配 98 | * DBError.ECJDBC_COMMUNITION_ERROR 所有站点都连不上 99 | */ 100 | func (g *epGroup) traverseServerList(connector *Connector, epSelector *epSelector, first bool, last bool) (*Connection, error) { 101 | epList := epSelector.sortDBList(first) 102 | errorMsg := bytes.NewBufferString("") 103 | var ex error = nil // 第一个错误 104 | for _, server := range epList { 105 | conn, err := server.connect(connector) 106 | if err != nil { 107 | if ex == nil { 108 | ex = err 109 | } 110 | errorMsg.WriteString("[") 111 | errorMsg.WriteString(server.String()) 112 | errorMsg.WriteString("]") 113 | errorMsg.WriteString(err.Error()) 114 | errorMsg.WriteString(util.StringUtil.LineSeparator()) 115 | continue 116 | } 117 | valid, err := epSelector.checkServerMode(conn, last) 118 | if err != nil { 119 | if ex == nil { 120 | ex = err 121 | } 122 | errorMsg.WriteString("[") 123 | errorMsg.WriteString(server.String()) 124 | errorMsg.WriteString("]") 125 | errorMsg.WriteString(err.Error()) 126 | errorMsg.WriteString(util.StringUtil.LineSeparator()) 127 | continue 128 | } 129 | if !valid { 130 | conn.close() 131 | err = ECGO_INVALID_SERVER_MODE.throw() 132 | if ex == nil { 133 | ex = err 134 | } 135 | errorMsg.WriteString("[") 136 | errorMsg.WriteString(server.String()) 137 | errorMsg.WriteString("]") 138 | errorMsg.WriteString(err.Error()) 139 | errorMsg.WriteString(util.StringUtil.LineSeparator()) 140 | continue 141 | } 142 | return conn, nil 143 | } 144 | if ex != nil { 145 | return nil, ex 146 | } 147 | return nil, ECGO_COMMUNITION_ERROR.addDetail(errorMsg.String()).throw() 148 | } 149 | -------------------------------------------------------------------------------- /z.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package dm 7 | 8 | import "sort" 9 | 10 | const ( 11 | TYPE_WELL_DISTRIBUTE = 0 12 | TYPE_HEAD_FIRST = 1 13 | ) 14 | 15 | type epSelector struct { 16 | dbs []*ep 17 | } 18 | 19 | func newEPSelector(dbs []*ep) *epSelector { 20 | return &epSelector{dbs} 21 | } 22 | 23 | func (s *epSelector) sortDBList(first bool) []*ep { 24 | if !first { 25 | // 按sort从大到小排序,相同sort值顺序不变 26 | sort.Slice(s.dbs, func(i, j int) bool { 27 | return s.dbs[i].getSort(first) > s.dbs[j].getSort(first) 28 | }) 29 | } 30 | return s.dbs 31 | } 32 | 33 | func (s *epSelector) checkServerMode(conn *Connection, last bool) (bool, error) { 34 | // 只连dsc control节点 35 | if conn.dmConnector.loginDscCtrl && !conn.dscControl { 36 | conn.close() 37 | return false, ECGO_INVALID_SERVER_MODE.throw() 38 | } 39 | // 模式不匹配, 这里使用的是连接之前的sort,连接之后server的状态可能发生改变sort也可能改变 40 | if conn.dmConnector.loginStatus > 0 && int(conn.SvrStat) != conn.dmConnector.loginStatus { 41 | conn.close() 42 | return false, ECGO_INVALID_SERVER_MODE.throw() 43 | } 44 | if last { 45 | switch conn.dmConnector.loginMode { 46 | case LOGIN_MODE_PRIMARY_ONLY: 47 | return conn.SvrMode == SERVER_MODE_PRIMARY, nil 48 | case LOGIN_MODE_STANDBY_ONLY: 49 | return conn.SvrMode == SERVER_MODE_STANDBY, nil 50 | default: 51 | return true, nil 52 | } 53 | } 54 | switch conn.dmConnector.loginMode { 55 | case LOGIN_MODE_NORMAL_FIRST: 56 | return conn.SvrMode == SERVER_MODE_NORMAL, nil 57 | case LOGIN_MODE_PRIMARY_FIRST, LOGIN_MODE_PRIMARY_ONLY: 58 | return conn.SvrMode == SERVER_MODE_PRIMARY, nil 59 | case LOGIN_MODE_STANDBY_FIRST, LOGIN_MODE_STANDBY_ONLY: 60 | return conn.SvrMode == SERVER_MODE_STANDBY, nil 61 | default: 62 | break 63 | } 64 | return false, nil 65 | } 66 | -------------------------------------------------------------------------------- /za.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package dm 7 | 8 | import ( 9 | "bytes" 10 | "fmt" 11 | "runtime" 12 | 13 | "github.com/gotomicro/dmgo/i18n" 14 | ) 15 | 16 | // 驱动级错误 17 | var ( 18 | DSN_INVALID_SCHEMA = newDmError(9001, "error.dsn.invalidSchema") 19 | UNSUPPORTED_SCAN = newDmError(9002, "error.unsupported.scan") 20 | INVALID_PARAMETER_NUMBER = newDmError(9003, "error.invalidParameterNumber") 21 | THIRD_PART_CIPHER_INIT_FAILED = newDmError(9004, "error.initThirdPartCipherFailed") 22 | ECGO_NOT_QUERY_SQL = newDmError(9005, "error.notQuerySQL") 23 | ECGO_NOT_EXEC_SQL = newDmError(9006, "error.notExecSQL") 24 | ECGO_UNKOWN_NETWORK = newDmError(9007, "error.unkownNetWork") 25 | ECGO_INVALID_CONN = newDmError(9008, "error.invalidConn") 26 | ECGO_UNSUPPORTED_INPARAM_TYPE = newDmError(9009, "error.unsupportedInparamType") 27 | ECGO_UNSUPPORTED_OUTPARAM_TYPE = newDmError(9010, "error.unsupportedOutparamType") 28 | ECGO_STORE_IN_NIL_POINTER = newDmError(9011, "error.storeInNilPointer") 29 | ) 30 | 31 | var ( 32 | ECGO_CONNECTION_SWITCH_FAILED = newDmError(20001, "error.connectionSwitchFailed") 33 | ECGO_CONNECTION_SWITCHED = newDmError(20000, "error.connectionSwitched") 34 | ECGO_COMMUNITION_ERROR = newDmError(6001, "error.communicationError") 35 | ECGO_MSG_CHECK_ERROR = newDmError(6002, "error.msgCheckError") 36 | ECGO_INVALID_TIME_INTERVAL = newDmError(6005, "error.invalidTimeInterval") 37 | ECGO_UNSUPPORTED_TYPE = newDmError(6006, "error.unsupportedType") 38 | ECGO_DATA_CONVERTION_ERROR = newDmError(6007, "error.dataConvertionError") 39 | ECGO_INVALID_SQL_TYPE = newDmError(6009, "error.invalidSqlType") 40 | ECGO_INVALID_DATETIME_FORMAT = newDmError(6015, "error.invalidDateTimeFormat") 41 | ECGO_INVALID_COLUMN_TYPE = newDmError(6016, "error.invalidColumnType") 42 | ECGO_RESULTSET_IS_READ_ONLY = newDmError(6029, "error.resultsetInReadOnlyStatus") 43 | ECGO_INVALID_SEQUENCE_NUMBER = newDmError(6032, "error.invalidSequenceNumber") 44 | ECGO_RESULTSET_CLOSED = newDmError(6034, "errorResultSetColsed") 45 | ECGO_STATEMENT_HANDLE_CLOSED = newDmError(6035, "errorStatementHandleClosed") 46 | ECGO_INVALID_PARAMETER_VALUE = newDmError(6036, "error.invalidParamterValue") 47 | ECGO_INVALID_TRAN_ISOLATION = newDmError(6038, "error.invalidTranIsolation") 48 | ECGO_COMMIT_IN_AUTOCOMMIT_MODE = newDmError(6039, "errorCommitInAutoCommitMode") 49 | ECGO_ROLLBACK_IN_AUTOCOMMIT_MODE = newDmError(6040, "errorRollbackInAutoCommitMode") 50 | ECGO_INVALID_LENGTH_OR_OFFSET = newDmError(6057, "error.invalidLenOrOffset") 51 | ECGO_INTERVAL_OVERFLOW = newDmError(6066, "error.intervalValueOverflow") 52 | ECGO_INVALID_BFILE_STR = newDmError(6067, "error.invalidBFile") 53 | ECGO_INVALID_HEX = newDmError(6068, "error.invalidHex") 54 | ECGO_INVALID_CIPHER = newDmError(6069, "error.invalidCipher") 55 | ECGO_OSAUTH_ERROR = newDmError(6073, "error.osauthError") 56 | ECGO_ERROR_SERVER_VERSION = newDmError(6074, "error.serverVersion") 57 | ECGO_USERNAME_TOO_LONG = newDmError(6075, "error.usernameTooLong") 58 | ECGO_PASSWORD_TOO_LONG = newDmError(6076, "error.passwordTooLong") 59 | ECGO_INVALID_COMPLEX_TYPE_NAME = newDmError(6079, "error.invalidComplexTypeName") 60 | ECGO_STRUCT_MEM_NOT_MATCH = newDmError(6080, "error.structMemNotMatch") 61 | ECGO_INVALID_OBJ_BLOB = newDmError(6081, "error.invalidObjBlob") 62 | ECGO_INVALID_ARRAY_LEN = newDmError(6082, "error.invalidArrayLen") 63 | ECGO_INVALID_SERVER_MODE = newDmError(6091, "error.invalidServerMode") 64 | ECGO_DATA_TOO_LONG = newDmError(6092, "error.dataTooLong") 65 | ECGO_BATCH_ERROR = newDmError(6093, "error.batchError") 66 | ECGO_INVALID_DATETIME_VALUE = newDmError(6103, "error.invalidDateTimeValue") 67 | 68 | ECGO_INIT_SSL_FAILED = newDmError(20002, "error.SSLInitFailed") 69 | ECGO_LOB_FREED = newDmError(20003, "error.LobDataHasFreed") 70 | ECGO_FATAL_ERROR = newDmError(20004, "error.fatalError") 71 | ) 72 | 73 | //Svr Msg Err 74 | var ( 75 | ECGO_DATA_OVERFLOW = newDmError(-6102, "error.dataOverflow") 76 | ECGO_DATETIME_OVERFLOW = newDmError(-6112, "error.datetimeOverflow") 77 | EC_RN_EXCEED_ROWSET_SIZE = newDmError(-7036, "") 78 | EC_BP_WITH_ERROR = newDmError(121, "warning.bpWithErr") 79 | ) 80 | 81 | type DmError struct { 82 | ErrCode int32 83 | ErrText string 84 | stack []uintptr 85 | detail string 86 | } 87 | 88 | func newDmError(errCode int32, errText string) *DmError { 89 | de := new(DmError) 90 | de.ErrCode = errCode 91 | de.ErrText = errText 92 | de.stack = nil 93 | de.detail = "" 94 | return de 95 | } 96 | 97 | func (dmError *DmError) throw() *DmError { 98 | var pcs [32]uintptr 99 | n := runtime.Callers(2, pcs[:]) 100 | dmError.stack = pcs[0:n] 101 | return dmError 102 | } 103 | 104 | func (dmError *DmError) FormatStack() string { 105 | if dmError == nil || dmError.stack == nil { 106 | return "" 107 | } 108 | buffer := bytes.NewBuffer(nil) 109 | index := 1 110 | space := " " 111 | for _, p := range dmError.stack { 112 | if fn := runtime.FuncForPC(p - 1); fn != nil { 113 | file, line := fn.FileLine(p - 1) 114 | buffer.WriteString(fmt.Sprintf(" %d).%s%s\n \t%s:%d\n", index, space, fn.Name(), file, line)) 115 | index++ 116 | } 117 | } 118 | return buffer.String() 119 | } 120 | 121 | func (dmError *DmError) Error() string { 122 | return fmt.Sprintf("Error %d: %s", dmError.ErrCode, i18n.Get(dmError.ErrText, Locale)) + dmError.detail + "\n" + "stack info:\n" + dmError.FormatStack() 123 | } 124 | 125 | // 扩充ErrText 126 | func (dmError *DmError) addDetail(detail string) *DmError { 127 | dmError.detail = detail 128 | return dmError 129 | } 130 | func (dmError *DmError) addDetailln(detail string) *DmError { 131 | return dmError.addDetail("\n" + detail) 132 | } 133 | -------------------------------------------------------------------------------- /zb.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package dm 7 | 8 | const ( 9 | IGNORE_TARGET_LENGTH int32 = -1 10 | 11 | IGNORE_TARGET_SCALE int32 = -1 12 | 13 | IGNORE_TARGET_TYPE = INT32_MIN 14 | 15 | TYPE_FLAG_UNKNOWN byte = 0 // 未知类型 16 | 17 | TYPE_FLAG_EXACT byte = 1 // 精确类型 18 | 19 | TYPE_FLAG_RECOMMEND byte = 2 // 推荐类型 20 | 21 | IO_TYPE_IN byte = 0 22 | 23 | IO_TYPE_OUT byte = 1 24 | 25 | IO_TYPE_INOUT byte = 2 26 | ) 27 | 28 | type execRetInfo struct { 29 | // param 30 | outParamDatas [][]byte 31 | 32 | // rs 33 | hasResultSet bool 34 | 35 | rsDatas [][][]byte 36 | 37 | rsSizeof int // 结果集数据占用多少空间,(消息中结果集起始位置到 rsCacheOffset 38 | // 的空间大小,这和实际的rsDatas占用空间大小有一定出入,这里粗略估算,用于结果集缓存时的空间管理) 39 | 40 | rsCacheOffset int32 // 缓存信息,在响应消息体中的偏移,0表示不存在,仅结果集缓存中可以用 41 | 42 | rsBdta bool 43 | 44 | rsUpdatable bool 45 | 46 | rsRowIds []int64 47 | 48 | // rs cache 49 | tbIds []int32 50 | 51 | tbTss []int64 52 | 53 | // print 54 | printLen int32 55 | 56 | printMsg string 57 | 58 | // explain 59 | explain string 60 | 61 | // 影响行数 62 | updateCount int64 // Insert/Update/Delet影响行数, select结果集的总行数 63 | 64 | updateCounts []int64 // 批量影响行数 65 | 66 | // 键 67 | rowid int64 68 | 69 | lastInsertId int64 70 | 71 | // other 72 | retSqlType int16 // 执行返回的语句类型 73 | 74 | execId int32 75 | } 76 | 77 | type column struct { 78 | typeName string 79 | 80 | colType int32 81 | 82 | prec int32 83 | 84 | scale int32 85 | 86 | name string 87 | 88 | tableName string 89 | 90 | schemaName string 91 | 92 | nullable bool 93 | 94 | identity bool 95 | 96 | readonly bool // 是否只读 97 | 98 | baseName string 99 | 100 | // lob info 101 | lob bool 102 | 103 | lobTabId int32 104 | 105 | lobColId int16 106 | 107 | // 用于描述ARRAY、STRUCT类型的特有描述信息 108 | typeDescriptor *TypeDescriptor 109 | 110 | isBdta bool 111 | } 112 | 113 | type parameter struct { 114 | column 115 | 116 | typeFlag byte 117 | 118 | ioType byte 119 | 120 | outJType int32 121 | 122 | outScale int32 123 | 124 | outObjectName string 125 | 126 | cursorStmt *DmStatement 127 | } 128 | 129 | func (column *column) InitColumn() *column { 130 | column.typeName = "" 131 | 132 | column.colType = 0 133 | 134 | column.prec = 0 135 | 136 | column.scale = 0 137 | 138 | column.name = "" 139 | 140 | column.tableName = "" 141 | 142 | column.schemaName = "" 143 | 144 | column.nullable = false 145 | 146 | column.identity = false 147 | 148 | column.readonly = false 149 | 150 | column.baseName = "" 151 | 152 | // lob info 153 | column.lob = false 154 | 155 | column.lobTabId = 0 156 | 157 | column.lobColId = 0 158 | 159 | // 用于描述ARRAY、STRUCT类型的特有描述信息 160 | column.typeDescriptor = nil 161 | 162 | column.isBdta = false 163 | 164 | return column 165 | } 166 | 167 | func (parameter *parameter) InitParameter() *parameter { 168 | parameter.InitColumn() 169 | 170 | parameter.typeFlag = TYPE_FLAG_UNKNOWN 171 | 172 | parameter.ioType = IO_TYPE_IN 173 | 174 | parameter.outJType = IGNORE_TARGET_TYPE 175 | 176 | parameter.outScale = IGNORE_TARGET_SCALE 177 | 178 | parameter.outObjectName = "" 179 | 180 | parameter.cursorStmt = nil 181 | 182 | return parameter 183 | } 184 | 185 | func (execInfo *execRetInfo) union(other *execRetInfo, startRow int, count int) { 186 | if count == 1 { 187 | execInfo.updateCounts[startRow] = other.updateCount 188 | } else if execInfo.updateCounts != nil { 189 | copy(execInfo.updateCounts[startRow:startRow+count], other.updateCounts[0:count]) 190 | } 191 | if execInfo.outParamDatas != nil { 192 | execInfo.outParamDatas = append(execInfo.outParamDatas, other.outParamDatas...) 193 | } 194 | } 195 | 196 | func NewExceInfo() *execRetInfo { 197 | 198 | execInfo := execRetInfo{} 199 | 200 | execInfo.outParamDatas = nil 201 | 202 | execInfo.hasResultSet = false 203 | 204 | execInfo.rsDatas = nil 205 | 206 | execInfo.rsSizeof = 0 207 | 208 | execInfo.rsCacheOffset = 0 209 | 210 | execInfo.rsBdta = false 211 | 212 | execInfo.rsUpdatable = false 213 | 214 | execInfo.rsRowIds = nil 215 | 216 | execInfo.tbIds = nil 217 | 218 | execInfo.tbTss = nil 219 | 220 | execInfo.printLen = 0 221 | 222 | execInfo.printMsg = "" 223 | 224 | execInfo.explain = "" 225 | 226 | execInfo.updateCount = 0 227 | 228 | execInfo.updateCounts = nil 229 | 230 | execInfo.rowid = -1 231 | 232 | execInfo.lastInsertId = 0 233 | // other 234 | execInfo.retSqlType = -1 // 执行返回的语句类型 235 | 236 | execInfo.execId = 0 237 | 238 | return &execInfo 239 | } 240 | -------------------------------------------------------------------------------- /zc.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | package dm 6 | 7 | import ( 8 | "context" 9 | "database/sql/driver" 10 | "reflect" 11 | "sync" 12 | "sync/atomic" 13 | "time" 14 | ) 15 | 16 | type filter interface { 17 | DmDriverOpen(filterChain *filterChain, d *Driver, dsn string) (*Connection, error) 18 | DmDriverOpenConnector(filterChain *filterChain, d *Driver, dsn string) (*Connector, error) 19 | 20 | DmConnectorConnect(filterChain *filterChain, c *Connector, ctx context.Context) (*Connection, error) 21 | DmConnectorDriver(filterChain *filterChain, c *Connector) *Driver 22 | 23 | DmConnectionBegin(filterChain *filterChain, c *Connection) (*Connection, error) 24 | DmConnectionBeginTx(filterChain *filterChain, c *Connection, ctx context.Context, opts driver.TxOptions) (*Connection, error) 25 | DmConnectionCommit(filterChain *filterChain, c *Connection) error 26 | DmConnectionRollback(filterChain *filterChain, c *Connection) error 27 | DmConnectionClose(filterChain *filterChain, c *Connection) error 28 | DmConnectionPing(filterChain *filterChain, c *Connection, ctx context.Context) error 29 | DmConnectionExec(filterChain *filterChain, c *Connection, query string, args []driver.Value) (*DmResult, error) 30 | DmConnectionExecContext(filterChain *filterChain, c *Connection, ctx context.Context, query string, args []driver.NamedValue) (*DmResult, error) 31 | DmConnectionQuery(filterChain *filterChain, c *Connection, query string, args []driver.Value) (*DmRows, error) 32 | DmConnectionQueryContext(filterChain *filterChain, c *Connection, ctx context.Context, query string, args []driver.NamedValue) (*DmRows, error) 33 | DmConnectionPrepare(filterChain *filterChain, c *Connection, query string) (*DmStatement, error) 34 | DmConnectionPrepareContext(filterChain *filterChain, c *Connection, ctx context.Context, query string) (*DmStatement, error) 35 | DmConnectionResetSession(filterChain *filterChain, c *Connection, ctx context.Context) error 36 | DmConnectionCheckNamedValue(filterChain *filterChain, c *Connection, nv *driver.NamedValue) error 37 | 38 | DmStatementClose(filterChain *filterChain, s *DmStatement) error 39 | DmStatementNumInput(filterChain *filterChain, s *DmStatement) int 40 | DmStatementExec(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmResult, error) 41 | DmStatementExecContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmResult, error) 42 | DmStatementQuery(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmRows, error) 43 | DmStatementQueryContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmRows, error) 44 | DmStatementCheckNamedValue(filterChain *filterChain, s *DmStatement, nv *driver.NamedValue) error 45 | 46 | DmResultLastInsertId(filterChain *filterChain, r *DmResult) (int64, error) 47 | DmResultRowsAffected(filterChain *filterChain, r *DmResult) (int64, error) 48 | 49 | DmRowsColumns(filterChain *filterChain, r *DmRows) []string 50 | DmRowsClose(filterChain *filterChain, r *DmRows) error 51 | DmRowsNext(filterChain *filterChain, r *DmRows, dest []driver.Value) error 52 | DmRowsHasNextResultSet(filterChain *filterChain, r *DmRows) bool 53 | DmRowsNextResultSet(filterChain *filterChain, r *DmRows) error 54 | DmRowsColumnTypeScanType(filterChain *filterChain, r *DmRows, index int) reflect.Type 55 | DmRowsColumnTypeDatabaseTypeName(filterChain *filterChain, r *DmRows, index int) string 56 | DmRowsColumnTypeLength(filterChain *filterChain, r *DmRows, index int) (length int64, ok bool) 57 | DmRowsColumnTypeNullable(filterChain *filterChain, r *DmRows, index int) (nullable, ok bool) 58 | DmRowsColumnTypePrecisionScale(filterChain *filterChain, r *DmRows, index int) (precision, scale int64, ok bool) 59 | } 60 | 61 | type IDGenerator int64 62 | 63 | var dmDriverIDGenerator = new(IDGenerator) 64 | var dmConntorIDGenerator = new(IDGenerator) 65 | var dmConnIDGenerator = new(IDGenerator) 66 | var dmStmtIDGenerator = new(IDGenerator) 67 | var dmResultIDGenerator = new(IDGenerator) 68 | var dmRowsIDGenerator = new(IDGenerator) 69 | 70 | func (g *IDGenerator) incrementAndGet() int64 { 71 | return atomic.AddInt64((*int64)(g), 1) 72 | } 73 | 74 | type RWSiteEnum int 75 | 76 | const ( 77 | PRIMARY RWSiteEnum = iota 78 | STANDBY 79 | ANYSITE 80 | ) 81 | 82 | var ( 83 | goMapMu sync.RWMutex 84 | goMap = make(map[string]goRun, 2) 85 | ) 86 | 87 | type filterable struct { 88 | filterChain *filterChain 89 | rwInfo *rwInfo 90 | logInfo *logInfo 91 | recoverInfo *recoverInfo 92 | statInfo *statInfo 93 | objId int64 94 | idGenerator *IDGenerator 95 | } 96 | 97 | func runLog() { 98 | goMapMu.Lock() 99 | _, ok := goMap["log"] 100 | if !ok { 101 | goMap["log"] = &logWriter{ 102 | flushQueue: make(chan []byte, LogFlushQueueSize), 103 | date: time.Now().Format("2006-01-02"), 104 | logFile: nil, 105 | flushFreq: LogFlushFreq, 106 | filePath: LogDir, 107 | filePrefix: "dm_go", 108 | buffer: Dm_build_1502(), 109 | } 110 | go goMap["log"].doRun() 111 | } 112 | goMapMu.Unlock() 113 | } 114 | 115 | func runStat() { 116 | goMapMu.Lock() 117 | _, ok := goMap["stat"] 118 | if !ok { 119 | goMap["stat"] = newStatFlusher() 120 | go goMap["stat"].doRun() 121 | } 122 | goMapMu.Unlock() 123 | } 124 | 125 | func (f *filterable) createFilterChain(bc *Connector, props *Properties) { 126 | var filters = make([]filter, 0, 5) 127 | 128 | if bc != nil { 129 | if LogLevel != LOG_OFF { 130 | filters = append(filters, &logFilter{}) 131 | f.logInfo = &logInfo{logRecord: new(LogRecord)} 132 | runLog() 133 | } 134 | 135 | if StatEnable { 136 | filters = append(filters, &statFilter{}) 137 | f.statInfo = newStatInfo() 138 | goStatMu.Lock() 139 | if goStat == nil { 140 | goStat = newGoStat(1000) 141 | } 142 | goStatMu.Unlock() 143 | runStat() 144 | } 145 | 146 | if bc.doSwitch != DO_SWITCH_OFF { 147 | filters = append(filters, &reconnectFilter{}) 148 | } 149 | 150 | if bc.rwSeparate { 151 | filters = append(filters, &rwFilter{}) 152 | f.rwInfo = newRwInfo() 153 | } 154 | } else if props != nil { 155 | if ParseLogLevel(props) != LOG_OFF { 156 | filters = append(filters, &logFilter{}) 157 | f.logInfo = &logInfo{logRecord: new(LogRecord)} 158 | runLog() 159 | } 160 | 161 | if props.GetBool("statEnable", StatEnable) { 162 | filters = append(filters, &statFilter{}) 163 | f.statInfo = newStatInfo() 164 | goStatMu.Lock() 165 | if goStat == nil { 166 | goStat = newGoStat(1000) 167 | } 168 | goStatMu.Unlock() 169 | runStat() 170 | } 171 | 172 | if props.GetInt(DoSwitchKey, int(DO_SWITCH_OFF), 0, 2) != int(DO_SWITCH_OFF) { 173 | filters = append(filters, &reconnectFilter{}) 174 | f.recoverInfo = newRecoverInfo() 175 | } 176 | 177 | if props.GetBool("rwSeparate", false) { 178 | filters = append(filters, &rwFilter{}) 179 | f.rwInfo = newRwInfo() 180 | } 181 | } 182 | 183 | f.filterChain = newFilterChain(filters) 184 | } 185 | 186 | func (f *filterable) resetFilterable(src *filterable) { 187 | f.filterChain = src.filterChain 188 | f.logInfo = src.logInfo 189 | f.rwInfo = src.rwInfo 190 | f.statInfo = src.statInfo 191 | } 192 | 193 | func (f filterable) getID() int64 { 194 | if f.objId < 0 { 195 | f.objId = f.idGenerator.incrementAndGet() 196 | } 197 | return f.objId 198 | } 199 | 200 | type logInfo struct { 201 | logRecord *LogRecord 202 | lastExecuteStartNano time.Time 203 | } 204 | 205 | type rwInfo struct { 206 | distribute RWSiteEnum 207 | 208 | rwCounter *rwCounter 209 | 210 | connStandby *Connection 211 | 212 | connCurrent *Connection 213 | 214 | tryRecoverTs int64 215 | 216 | stmtStandby *DmStatement 217 | 218 | stmtCurrent *DmStatement 219 | 220 | readOnly bool 221 | } 222 | 223 | func newRwInfo() *rwInfo { 224 | rwInfo := new(rwInfo) 225 | rwInfo.distribute = PRIMARY 226 | rwInfo.readOnly = true 227 | return rwInfo 228 | } 229 | 230 | func (rwi *rwInfo) cleanup() { 231 | rwi.distribute = PRIMARY 232 | rwi.rwCounter = nil 233 | rwi.connStandby = nil 234 | rwi.connCurrent = nil 235 | rwi.stmtStandby = nil 236 | rwi.stmtCurrent = nil 237 | } 238 | 239 | func (rwi *rwInfo) toPrimary() RWSiteEnum { 240 | if rwi.distribute != PRIMARY { 241 | 242 | rwi.rwCounter.countPrimary() 243 | } 244 | rwi.distribute = PRIMARY 245 | return rwi.distribute 246 | } 247 | 248 | func (rwi *rwInfo) toAny() RWSiteEnum { 249 | 250 | rwi.distribute = rwi.rwCounter.count(ANYSITE, rwi.connStandby) 251 | return rwi.distribute 252 | } 253 | 254 | type recoverInfo struct { 255 | checkEpRecoverTs int64 256 | } 257 | 258 | func newRecoverInfo() *recoverInfo { 259 | recoverInfo := new(recoverInfo) 260 | recoverInfo.checkEpRecoverTs = 0 261 | return recoverInfo 262 | } 263 | 264 | type statInfo struct { 265 | constructNano int64 266 | 267 | connStat *connectionStat 268 | 269 | lastExecuteStartNano int64 270 | 271 | lastExecuteTimeNano int64 272 | 273 | lastExecuteType ExecuteTypeEnum 274 | 275 | firstResultSet bool 276 | 277 | lastExecuteSql string 278 | 279 | sqlStat *sqlStat 280 | 281 | sql string 282 | 283 | cursorIndex int 284 | 285 | closeCount int 286 | 287 | readStringLength int64 288 | 289 | readBytesLength int64 290 | 291 | openInputStreamCount int 292 | 293 | openReaderCount int 294 | } 295 | 296 | var ( 297 | goStatMu sync.RWMutex 298 | goStat *GoStat 299 | ) 300 | 301 | func newStatInfo() *statInfo { 302 | si := new(statInfo) 303 | return si 304 | } 305 | func (si *statInfo) init(conn *Connection) { 306 | si.connStat = goStat.createConnStat(conn) 307 | } 308 | 309 | func (si *statInfo) setConstructNano() { 310 | si.constructNano = time.Now().UnixNano() 311 | } 312 | 313 | func (si *statInfo) getConstructNano() int64 { 314 | return si.constructNano 315 | } 316 | 317 | func (si *statInfo) getConnStat() *connectionStat { 318 | return si.connStat 319 | } 320 | 321 | func (si *statInfo) getLastExecuteStartNano() int64 { 322 | return si.lastExecuteStartNano 323 | } 324 | 325 | func (si *statInfo) setLastExecuteStartNano(lastExecuteStartNano int64) { 326 | si.lastExecuteStartNano = lastExecuteStartNano 327 | } 328 | 329 | func (si *statInfo) getLastExecuteTimeNano() int64 { 330 | return si.lastExecuteTimeNano 331 | } 332 | 333 | func (si *statInfo) setLastExecuteTimeNano(lastExecuteTimeNano int64) { 334 | si.lastExecuteTimeNano = lastExecuteTimeNano 335 | } 336 | 337 | func (si *statInfo) getLastExecuteType() ExecuteTypeEnum { 338 | return si.lastExecuteType 339 | } 340 | 341 | func (si *statInfo) setLastExecuteType(lastExecuteType ExecuteTypeEnum) { 342 | si.lastExecuteType = lastExecuteType 343 | } 344 | 345 | func (si *statInfo) isFirstResultSet() bool { 346 | return si.firstResultSet 347 | } 348 | 349 | func (si *statInfo) setFirstResultSet(firstResultSet bool) { 350 | si.firstResultSet = firstResultSet 351 | } 352 | 353 | func (si *statInfo) getLastExecuteSql() string { 354 | return si.lastExecuteSql 355 | } 356 | 357 | func (si *statInfo) setLastExecuteSql(lastExecuteSql string) { 358 | si.lastExecuteSql = lastExecuteSql 359 | } 360 | 361 | func (si *statInfo) getSqlStat() *sqlStat { 362 | return si.sqlStat 363 | } 364 | 365 | func (si *statInfo) setSqlStat(sqlStat *sqlStat) { 366 | si.sqlStat = sqlStat 367 | } 368 | 369 | func (si *statInfo) setConnStat(connStat *connectionStat) { 370 | si.connStat = connStat 371 | } 372 | 373 | func (si *statInfo) setConstructNanoWithConstructNano(constructNano int64) { 374 | si.constructNano = constructNano 375 | } 376 | 377 | func (si *statInfo) afterExecute(nanoSpan int64) { 378 | si.lastExecuteTimeNano = nanoSpan 379 | } 380 | 381 | func (si *statInfo) beforeExecute() { 382 | si.lastExecuteStartNano = time.Now().UnixNano() 383 | } 384 | 385 | func (si *statInfo) getSql() string { 386 | return si.sql 387 | } 388 | 389 | func (si *statInfo) setSql(sql string) { 390 | si.sql = sql 391 | } 392 | 393 | func (si *statInfo) getCursorIndex() int { 394 | return si.cursorIndex 395 | } 396 | 397 | func (si *statInfo) setCursorIndex(cursorIndex int) { 398 | si.cursorIndex = cursorIndex 399 | } 400 | 401 | func (si *statInfo) getCloseCount() int { 402 | return si.closeCount 403 | } 404 | 405 | func (si *statInfo) setCloseCount(closeCount int) { 406 | si.closeCount = closeCount 407 | } 408 | 409 | func (si *statInfo) getReadStringLength() int64 { 410 | return si.readStringLength 411 | } 412 | 413 | func (si *statInfo) setReadStringLength(readStringLength int64) { 414 | si.readStringLength = readStringLength 415 | } 416 | 417 | func (si *statInfo) getReadBytesLength() int64 { 418 | return si.readBytesLength 419 | } 420 | 421 | func (si *statInfo) setReadBytesLength(readBytesLength int64) { 422 | si.readBytesLength = readBytesLength 423 | } 424 | 425 | func (si *statInfo) getOpenInputStreamCount() int { 426 | return si.openInputStreamCount 427 | } 428 | 429 | func (si *statInfo) setOpenInputStreamCount(openInputStreamCount int) { 430 | si.openInputStreamCount = openInputStreamCount 431 | } 432 | 433 | func (si *statInfo) getOpenReaderCount() int { 434 | return si.openReaderCount 435 | } 436 | 437 | func (si *statInfo) setOpenReaderCount(openReaderCount int) { 438 | si.openReaderCount = openReaderCount 439 | } 440 | 441 | func (si *statInfo) incrementCloseCount() { 442 | si.closeCount++ 443 | } 444 | -------------------------------------------------------------------------------- /zg.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package dm 7 | 8 | import ( 9 | "context" 10 | "database/sql/driver" 11 | "reflect" 12 | ) 13 | 14 | type rwFilter struct { 15 | } 16 | 17 | //DmDriver 18 | func (rwf *rwFilter) DmDriverOpen(filterChain *filterChain, d *Driver, dsn string) (*Connection, error) { 19 | return filterChain.DmDriverOpen(d, dsn) 20 | } 21 | 22 | func (rwf *rwFilter) DmDriverOpenConnector(filterChain *filterChain, d *Driver, dsn string) (*Connector, error) { 23 | return filterChain.DmDriverOpenConnector(d, dsn) 24 | } 25 | 26 | //DmConnector 27 | func (rwf *rwFilter) DmConnectorConnect(filterChain *filterChain, c *Connector, ctx context.Context) (*Connection, error) { 28 | return RWUtil.connect(c, ctx) 29 | } 30 | 31 | func (rwf *rwFilter) DmConnectorDriver(filterChain *filterChain, c *Connector) *Driver { 32 | return filterChain.DmConnectorDriver(c) 33 | } 34 | 35 | //DmConnection 36 | func (rwf *rwFilter) DmConnectionBegin(filterChain *filterChain, c *Connection) (*Connection, error) { 37 | if RWUtil.isStandbyAlive(c) { 38 | _, err := c.rwInfo.connStandby.begin() 39 | if err != nil { 40 | RWUtil.afterExceptionOnStandby(c, err) 41 | } 42 | } 43 | 44 | return filterChain.DmConnectionBegin(c) 45 | } 46 | 47 | func (rwf *rwFilter) DmConnectionBeginTx(filterChain *filterChain, c *Connection, ctx context.Context, opts driver.TxOptions) (*Connection, error) { 48 | if RWUtil.isStandbyAlive(c) { 49 | _, err := c.rwInfo.connStandby.beginTx(ctx, opts) 50 | if err != nil { 51 | RWUtil.afterExceptionOnStandby(c, err) 52 | } 53 | } 54 | 55 | return filterChain.DmConnectionBeginTx(c, ctx, opts) 56 | } 57 | 58 | func (rwf *rwFilter) DmConnectionCommit(filterChain *filterChain, c *Connection) error { 59 | if RWUtil.isStandbyAlive(c) { 60 | err := c.rwInfo.connStandby.commit() 61 | if err != nil { 62 | RWUtil.afterExceptionOnStandby(c, err) 63 | } 64 | } 65 | 66 | return filterChain.DmConnectionCommit(c) 67 | } 68 | 69 | func (rwf *rwFilter) DmConnectionRollback(filterChain *filterChain, c *Connection) error { 70 | if RWUtil.isStandbyAlive(c) { 71 | err := c.rwInfo.connStandby.rollback() 72 | if err != nil { 73 | RWUtil.afterExceptionOnStandby(c, err) 74 | } 75 | } 76 | 77 | return filterChain.DmConnectionRollback(c) 78 | } 79 | 80 | func (rwf *rwFilter) DmConnectionClose(filterChain *filterChain, c *Connection) error { 81 | if RWUtil.isStandbyAlive(c) { 82 | err := c.rwInfo.connStandby.close() 83 | if err != nil { 84 | RWUtil.afterExceptionOnStandby(c, err) 85 | } 86 | } 87 | 88 | return filterChain.DmConnectionClose(c) 89 | } 90 | 91 | func (rwf *rwFilter) DmConnectionPing(filterChain *filterChain, c *Connection, ctx context.Context) error { 92 | return filterChain.DmConnectionPing(c, ctx) 93 | } 94 | 95 | func (rwf *rwFilter) DmConnectionExec(filterChain *filterChain, c *Connection, query string, args []driver.Value) (*DmResult, error) { 96 | ret, err := RWUtil.executeByConn(c, query, func() (interface{}, error) { 97 | return c.rwInfo.connCurrent.exec(query, args) 98 | }, func(otherConn *Connection) (interface{}, error) { 99 | return otherConn.exec(query, args) 100 | }) 101 | if err != nil { 102 | return nil, err 103 | } 104 | return ret.(*DmResult), nil 105 | } 106 | 107 | func (rwf *rwFilter) DmConnectionExecContext(filterChain *filterChain, c *Connection, ctx context.Context, query string, args []driver.NamedValue) (*DmResult, error) { 108 | ret, err := RWUtil.executeByConn(c, query, func() (interface{}, error) { 109 | return c.rwInfo.connCurrent.execContext(ctx, query, args) 110 | }, func(otherConn *Connection) (interface{}, error) { 111 | return otherConn.execContext(ctx, query, args) 112 | }) 113 | if err != nil { 114 | return nil, err 115 | } 116 | return ret.(*DmResult), nil 117 | } 118 | 119 | func (rwf *rwFilter) DmConnectionQuery(filterChain *filterChain, c *Connection, query string, args []driver.Value) (*DmRows, error) { 120 | ret, err := RWUtil.executeByConn(c, query, func() (interface{}, error) { 121 | return c.rwInfo.connCurrent.query(query, args) 122 | }, func(otherConn *Connection) (interface{}, error) { 123 | return otherConn.query(query, args) 124 | }) 125 | if err != nil { 126 | return nil, err 127 | } 128 | return ret.(*DmRows), nil 129 | } 130 | 131 | func (rwf *rwFilter) DmConnectionQueryContext(filterChain *filterChain, c *Connection, ctx context.Context, query string, args []driver.NamedValue) (*DmRows, error) { 132 | ret, err := RWUtil.executeByConn(c, query, func() (interface{}, error) { 133 | return c.rwInfo.connCurrent.queryContext(ctx, query, args) 134 | }, func(otherConn *Connection) (interface{}, error) { 135 | return otherConn.queryContext(ctx, query, args) 136 | }) 137 | if err != nil { 138 | return nil, err 139 | } 140 | return ret.(*DmRows), nil 141 | } 142 | 143 | func (rwf *rwFilter) DmConnectionPrepare(filterChain *filterChain, c *Connection, query string) (*DmStatement, error) { 144 | stmt, err := c.prepare(query) 145 | if err != nil { 146 | return nil, err 147 | } 148 | stmt.rwInfo.stmtCurrent = stmt 149 | stmt.rwInfo.readOnly = RWUtil.checkReadonlyByStmt(stmt) 150 | if RWUtil.isCreateStandbyStmt(stmt) { 151 | stmt.rwInfo.stmtStandby, err = c.rwInfo.connStandby.prepare(query) 152 | if err == nil { 153 | stmt.rwInfo.stmtCurrent = stmt.rwInfo.stmtStandby 154 | } else { 155 | RWUtil.afterExceptionOnStandby(c, err) 156 | } 157 | } 158 | return stmt, nil 159 | } 160 | 161 | func (rwf *rwFilter) DmConnectionPrepareContext(filterChain *filterChain, c *Connection, ctx context.Context, query string) (*DmStatement, error) { 162 | stmt, err := c.prepareContext(ctx, query) 163 | if err != nil { 164 | return nil, err 165 | } 166 | stmt.rwInfo.stmtCurrent = stmt 167 | stmt.rwInfo.readOnly = RWUtil.checkReadonlyByStmt(stmt) 168 | if RWUtil.isCreateStandbyStmt(stmt) { 169 | stmt.rwInfo.stmtStandby, err = c.rwInfo.connStandby.prepareContext(ctx, query) 170 | if err == nil { 171 | stmt.rwInfo.stmtCurrent = stmt.rwInfo.stmtStandby 172 | } else { 173 | RWUtil.afterExceptionOnStandby(c, err) 174 | } 175 | } 176 | return stmt, nil 177 | } 178 | 179 | func (rwf *rwFilter) DmConnectionResetSession(filterChain *filterChain, c *Connection, ctx context.Context) error { 180 | if RWUtil.isStandbyAlive(c) { 181 | err := c.rwInfo.connStandby.resetSession(ctx) 182 | if err != nil { 183 | RWUtil.afterExceptionOnStandby(c, err) 184 | } 185 | } 186 | 187 | return filterChain.DmConnectionResetSession(c, ctx) 188 | } 189 | 190 | func (rwf *rwFilter) DmConnectionCheckNamedValue(filterChain *filterChain, c *Connection, nv *driver.NamedValue) error { 191 | return filterChain.DmConnectionCheckNamedValue(c, nv) 192 | } 193 | 194 | //DmStatement 195 | func (rwf *rwFilter) DmStatementClose(filterChain *filterChain, s *DmStatement) error { 196 | if RWUtil.isStandbyStatementValid(s) { 197 | err := s.rwInfo.stmtStandby.close() 198 | if err != nil { 199 | RWUtil.afterExceptionOnStandby(s.dmConn, err) 200 | } 201 | } 202 | 203 | return filterChain.DmStatementClose(s) 204 | } 205 | 206 | func (rwf *rwFilter) DmStatementNumInput(filterChain *filterChain, s *DmStatement) int { 207 | return filterChain.DmStatementNumInput(s) 208 | } 209 | 210 | func (rwf *rwFilter) DmStatementExec(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmResult, error) { 211 | ret, err := RWUtil.executeByStmt(s, func() (interface{}, error) { 212 | return s.rwInfo.stmtCurrent.exec(args) 213 | }, func(otherStmt *DmStatement) (interface{}, error) { 214 | return otherStmt.exec(args) 215 | }) 216 | if err != nil { 217 | return nil, err 218 | } 219 | return ret.(*DmResult), nil 220 | } 221 | 222 | func (rwf *rwFilter) DmStatementExecContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmResult, error) { 223 | ret, err := RWUtil.executeByStmt(s, func() (interface{}, error) { 224 | return s.rwInfo.stmtCurrent.execContext(ctx, args) 225 | }, func(otherStmt *DmStatement) (interface{}, error) { 226 | return otherStmt.execContext(ctx, args) 227 | }) 228 | if err != nil { 229 | return nil, err 230 | } 231 | return ret.(*DmResult), nil 232 | } 233 | 234 | func (rwf *rwFilter) DmStatementQuery(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmRows, error) { 235 | ret, err := RWUtil.executeByStmt(s, func() (interface{}, error) { 236 | return s.rwInfo.stmtCurrent.query(args) 237 | }, func(otherStmt *DmStatement) (interface{}, error) { 238 | return otherStmt.query(args) 239 | }) 240 | if err != nil { 241 | return nil, err 242 | } 243 | return ret.(*DmRows), nil 244 | } 245 | 246 | func (rwf *rwFilter) DmStatementQueryContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmRows, error) { 247 | ret, err := RWUtil.executeByStmt(s, func() (interface{}, error) { 248 | return s.rwInfo.stmtCurrent.queryContext(ctx, args) 249 | }, func(otherStmt *DmStatement) (interface{}, error) { 250 | return otherStmt.queryContext(ctx, args) 251 | }) 252 | if err != nil { 253 | return nil, err 254 | } 255 | return ret.(*DmRows), nil 256 | } 257 | 258 | func (rwf *rwFilter) DmStatementCheckNamedValue(filterChain *filterChain, s *DmStatement, nv *driver.NamedValue) error { 259 | return filterChain.DmStatementCheckNamedValue(s, nv) 260 | } 261 | 262 | //DmResult 263 | func (rwf *rwFilter) DmResultLastInsertId(filterChain *filterChain, r *DmResult) (int64, error) { 264 | return filterChain.DmResultLastInsertId(r) 265 | } 266 | 267 | func (rwf *rwFilter) DmResultRowsAffected(filterChain *filterChain, r *DmResult) (int64, error) { 268 | return filterChain.DmResultRowsAffected(r) 269 | } 270 | 271 | //DmRows 272 | func (rwf *rwFilter) DmRowsColumns(filterChain *filterChain, r *DmRows) []string { 273 | return filterChain.DmRowsColumns(r) 274 | } 275 | 276 | func (rwf *rwFilter) DmRowsClose(filterChain *filterChain, r *DmRows) error { 277 | return filterChain.DmRowsClose(r) 278 | } 279 | 280 | func (rwf *rwFilter) DmRowsNext(filterChain *filterChain, r *DmRows, dest []driver.Value) error { 281 | return filterChain.DmRowsNext(r, dest) 282 | } 283 | 284 | func (rwf *rwFilter) DmRowsHasNextResultSet(filterChain *filterChain, r *DmRows) bool { 285 | return filterChain.DmRowsHasNextResultSet(r) 286 | } 287 | 288 | func (rwf *rwFilter) DmRowsNextResultSet(filterChain *filterChain, r *DmRows) error { 289 | return filterChain.DmRowsNextResultSet(r) 290 | } 291 | 292 | func (rwf *rwFilter) DmRowsColumnTypeScanType(filterChain *filterChain, r *DmRows, index int) reflect.Type { 293 | return filterChain.DmRowsColumnTypeScanType(r, index) 294 | } 295 | 296 | func (rwf *rwFilter) DmRowsColumnTypeDatabaseTypeName(filterChain *filterChain, r *DmRows, index int) string { 297 | return filterChain.DmRowsColumnTypeDatabaseTypeName(r, index) 298 | } 299 | 300 | func (rwf *rwFilter) DmRowsColumnTypeLength(filterChain *filterChain, r *DmRows, index int) (length int64, ok bool) { 301 | return filterChain.DmRowsColumnTypeLength(r, index) 302 | } 303 | 304 | func (rwf *rwFilter) DmRowsColumnTypeNullable(filterChain *filterChain, r *DmRows, index int) (nullable, ok bool) { 305 | return filterChain.DmRowsColumnTypeNullable(r, index) 306 | } 307 | 308 | func (rwf *rwFilter) DmRowsColumnTypePrecisionScale(filterChain *filterChain, r *DmRows, index int) (precision, scale int64, ok bool) { 309 | return filterChain.DmRowsColumnTypePrecisionScale(r, index) 310 | } 311 | -------------------------------------------------------------------------------- /zn.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | package dm 6 | 7 | const ( 8 | LOB_FLAG_BYTE = 0 9 | LOB_FLAG_CHAR = 1 10 | 11 | LOB_IN_ROW = 0x1 12 | LOB_OFF_ROW = 0x2 13 | 14 | NBLOB_HEAD_IN_ROW_FLAG = 0 15 | NBLOB_HEAD_BLOBID = NBLOB_HEAD_IN_ROW_FLAG + BYTE_SIZE 16 | NBLOB_HEAD_BLOB_LEN = NBLOB_HEAD_BLOBID + DDWORD_SIZE 17 | 18 | NBLOB_HEAD_OUTROW_GROUPID = NBLOB_HEAD_BLOB_LEN + ULINT_SIZE 19 | NBLOB_HEAD_OUTROW_FILEID = NBLOB_HEAD_OUTROW_GROUPID + USINT_SIZE 20 | NBLOB_HEAD_OUTROW_PAGENO = NBLOB_HEAD_OUTROW_FILEID + USINT_SIZE 21 | 22 | NBLOB_EX_HEAD_TABLE_ID = NBLOB_HEAD_OUTROW_PAGENO + ULINT_SIZE 23 | NBLOB_EX_HEAD_COL_ID = NBLOB_EX_HEAD_TABLE_ID + ULINT_SIZE 24 | NBLOB_EX_HEAD_ROW_ID = NBLOB_EX_HEAD_COL_ID + USINT_SIZE 25 | NBLOB_EX_HEAD_FPA_GRPID = NBLOB_EX_HEAD_ROW_ID + LINT64_SIZE 26 | NBLOB_EX_HEAD_FPA_FILEID = NBLOB_EX_HEAD_FPA_GRPID + USINT_SIZE 27 | NBLOB_EX_HEAD_FPA_PAGENO = NBLOB_EX_HEAD_FPA_FILEID + USINT_SIZE 28 | NBLOB_EX_HEAD_SIZE = NBLOB_EX_HEAD_FPA_PAGENO + ULINT_SIZE 29 | 30 | NBLOB_OUTROW_HEAD_SIZE = NBLOB_HEAD_OUTROW_PAGENO + ULINT_SIZE 31 | 32 | NBLOB_INROW_HEAD_SIZE = NBLOB_HEAD_BLOB_LEN + ULINT_SIZE 33 | ) 34 | 35 | type lob struct { 36 | blobId int64 37 | inRow bool 38 | 39 | groupId int16 40 | fileId int16 41 | pageNo int32 42 | tabId int32 43 | colId int16 44 | rowId int64 45 | exGroupId int16 46 | exFileId int16 47 | exPageNo int32 48 | 49 | curFileId int16 50 | curPageNo int32 51 | curPageOffset int16 52 | totalOffset int32 53 | readOver bool 54 | 55 | connection *Connection 56 | local bool 57 | updateable bool 58 | lobFlag int8 59 | length int64 60 | compatibleOracle bool 61 | fetchAll bool 62 | freed bool 63 | modify bool 64 | } 65 | 66 | func (lob *lob) checkFreed() (err error) { 67 | if lob.freed { 68 | err = ECGO_LOB_FREED.throw() 69 | } 70 | return 71 | } 72 | 73 | func (lob *lob) GetLength() (int64, error) { 74 | var err error 75 | if err := lob.checkFreed(); err != nil { 76 | return -1, err 77 | } 78 | if lob.length == -1 { 79 | 80 | if lob.length, err = lob.connection.Access.dm_build_491(lob); err != nil { 81 | return -1, err 82 | } 83 | } 84 | return lob.length, nil 85 | } 86 | 87 | func (lob *lob) resetCurrentInfo() { 88 | lob.curFileId = lob.fileId 89 | lob.curPageNo = lob.pageNo 90 | lob.totalOffset = 0 91 | lob.curPageOffset = 0 92 | } 93 | 94 | func (lob *lob) getLengthFromHead(head []byte) int64 { 95 | return int64(Dm_build_1219.Dm_build_1321(head, NBLOB_HEAD_BLOB_LEN)) 96 | } 97 | 98 | func (lob *lob) canOptimized(connection *Connection) bool { 99 | return !(lob.inRow || lob.fetchAll || lob.local || connection != lob.connection) 100 | } 101 | 102 | func (lob *lob) buildCtlData() (bytes []byte) { 103 | if lob.connection.NewLobFlag { 104 | bytes = make([]byte, NBLOB_EX_HEAD_SIZE, NBLOB_EX_HEAD_SIZE) 105 | } else { 106 | bytes = make([]byte, NBLOB_OUTROW_HEAD_SIZE, NBLOB_OUTROW_HEAD_SIZE) 107 | } 108 | Dm_build_1219.Dm_build_1220(bytes, NBLOB_HEAD_IN_ROW_FLAG, LOB_OFF_ROW) 109 | Dm_build_1219.Dm_build_1240(bytes, NBLOB_HEAD_BLOBID, lob.blobId) 110 | Dm_build_1219.Dm_build_1235(bytes, NBLOB_HEAD_BLOB_LEN, -1) 111 | 112 | Dm_build_1219.Dm_build_1230(bytes, NBLOB_HEAD_OUTROW_GROUPID, lob.groupId) 113 | Dm_build_1219.Dm_build_1230(bytes, NBLOB_HEAD_OUTROW_FILEID, lob.fileId) 114 | Dm_build_1219.Dm_build_1235(bytes, NBLOB_HEAD_OUTROW_PAGENO, lob.pageNo) 115 | 116 | if lob.connection.NewLobFlag { 117 | Dm_build_1219.Dm_build_1235(bytes, NBLOB_EX_HEAD_TABLE_ID, lob.tabId) 118 | Dm_build_1219.Dm_build_1230(bytes, NBLOB_EX_HEAD_COL_ID, lob.colId) 119 | Dm_build_1219.Dm_build_1240(bytes, NBLOB_EX_HEAD_ROW_ID, lob.rowId) 120 | Dm_build_1219.Dm_build_1230(bytes, NBLOB_EX_HEAD_FPA_GRPID, lob.exGroupId) 121 | Dm_build_1219.Dm_build_1230(bytes, NBLOB_EX_HEAD_FPA_FILEID, lob.exFileId) 122 | Dm_build_1219.Dm_build_1235(bytes, NBLOB_EX_HEAD_FPA_PAGENO, lob.exPageNo) 123 | } 124 | return 125 | } 126 | -------------------------------------------------------------------------------- /zo.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package dm 7 | 8 | const ( 9 | ParamDataEnum_Null = 0 10 | /** 11 | * 只有大字段才有行内数据、行外数据的概念 12 | */ 13 | ParamDataEnum_OFF_ROW = 1 14 | ) 15 | 16 | type lobCtl struct { 17 | value []byte 18 | } 19 | -------------------------------------------------------------------------------- /zp.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | package dm 6 | 7 | import ( 8 | "os" 9 | "strconv" 10 | "strings" 11 | "time" 12 | 13 | "github.com/gotomicro/dmgo/util" 14 | ) 15 | 16 | const ( 17 | MAX_FILE_SIZE = 100 * 1024 * 1024 18 | FLUSH_SIZE = 32 * 1024 19 | ) 20 | 21 | type goRun interface { 22 | doRun() 23 | } 24 | 25 | type logWriter struct { 26 | flushQueue chan []byte 27 | date string 28 | logFile *os.File 29 | flushFreq int 30 | filePath string 31 | filePrefix string 32 | buffer *Dm_build_1498 33 | } 34 | 35 | func (lw *logWriter) doRun() { 36 | defer func() { 37 | lw.beforeExit() 38 | lw.closeCurrentFile() 39 | }() 40 | 41 | i := 0 42 | for { 43 | var ibytes []byte 44 | 45 | select { 46 | case ibytes = <-lw.flushQueue: 47 | if LogLevel != LOG_OFF { 48 | if i == LogFlushQueueSize { 49 | lw.doFlush(lw.buffer) 50 | i = 0 51 | } else { 52 | lw.buffer.Dm_build_1524(ibytes, 0, len(ibytes)) 53 | i++ 54 | } 55 | } 56 | case <-time.After(time.Duration(LogFlushFreq) * time.Millisecond): 57 | if LogLevel != LOG_OFF && lw.buffer.Dm_build_1503() > 0 { 58 | lw.doFlush(lw.buffer) 59 | i = 0 60 | } 61 | 62 | } 63 | 64 | } 65 | } 66 | 67 | func (lw *logWriter) doFlush(buffer *Dm_build_1498) { 68 | if lw.needCreateNewFile() { 69 | lw.closeCurrentFile() 70 | lw.logFile = lw.createNewFile() 71 | } 72 | buffer.Dm_build_1518(lw.logFile, buffer.Dm_build_1503()) 73 | } 74 | func (lw *logWriter) closeCurrentFile() { 75 | if lw.logFile != nil { 76 | lw.logFile.Close() 77 | lw.logFile = nil 78 | } 79 | } 80 | func (lw *logWriter) createNewFile() *os.File { 81 | lw.date = time.Now().Format("2006-01-02") 82 | fileName := lw.filePrefix + "_" + lw.date + "_" + strconv.Itoa(time.Now().Nanosecond()) + ".log" 83 | lw.filePath = LogDir 84 | if len(lw.filePath) > 0 { 85 | if _, err := os.Stat(lw.filePath); err != nil { 86 | os.MkdirAll(lw.filePath, 0755) 87 | } 88 | if _, err := os.Stat(lw.filePath + fileName); err != nil { 89 | logFile, err := os.Create(lw.filePath + fileName) 90 | if err != nil { 91 | panic(err) 92 | } 93 | return logFile 94 | } 95 | } 96 | return nil 97 | } 98 | func (lw *logWriter) needCreateNewFile() bool { 99 | now := time.Now().Format("2006-01-02") 100 | fileInfo, err := lw.logFile.Stat() 101 | return now != lw.date || err != nil || lw.logFile == nil || fileInfo.Size() > int64(MAX_FILE_SIZE) 102 | } 103 | func (lw *logWriter) beforeExit() { 104 | close(lw.flushQueue) 105 | var ibytes []byte 106 | for ibytes = <-lw.flushQueue; ibytes != nil; ibytes = <-lw.flushQueue { 107 | lw.buffer.Dm_build_1524(ibytes, 0, len(ibytes)) 108 | if lw.buffer.Dm_build_1503() >= LogBufferSize { 109 | lw.doFlush(lw.buffer) 110 | } 111 | } 112 | if lw.buffer.Dm_build_1503() > 0 { 113 | lw.doFlush(lw.buffer) 114 | } 115 | } 116 | 117 | func (lw *logWriter) WriteLine(msg string) { 118 | var b = []byte(strings.TrimSpace(msg) + util.LINE_SEPARATOR) 119 | lw.flushQueue <- b 120 | } 121 | -------------------------------------------------------------------------------- /zr.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | package dm 6 | 7 | import ( 8 | "io" 9 | ) 10 | 11 | const ( 12 | READ_LEN = Dm_build_716 13 | ) 14 | 15 | type iOffRowBinder interface { 16 | read(buf *Dm_build_1498) 17 | isReadOver() bool 18 | getObj() interface{} 19 | } 20 | 21 | type offRowBinder struct { 22 | obj interface{} 23 | encoding string 24 | readOver bool 25 | buffer *Dm_build_1498 26 | position int32 27 | offRow bool 28 | targetLength int64 29 | } 30 | 31 | func newOffRowBinder(obj interface{}, encoding string, targetLength int64) *offRowBinder { 32 | return &offRowBinder{ 33 | obj: obj, 34 | encoding: encoding, 35 | targetLength: targetLength, 36 | readOver: false, 37 | buffer: Dm_build_1502(), 38 | position: 0, 39 | } 40 | } 41 | 42 | type offRowBytesBinder struct { 43 | *offRowBinder 44 | } 45 | 46 | func newOffRowBytesBinder(obj []byte, encoding string) *offRowBytesBinder { 47 | var binder = &offRowBytesBinder{ 48 | newOffRowBinder(obj, encoding, int64(IGNORE_TARGET_LENGTH)), 49 | } 50 | binder.read(binder.buffer) 51 | binder.offRow = binder.buffer.Dm_build_1503() > Dm_build_713 52 | return binder 53 | } 54 | 55 | func (b *offRowBytesBinder) read(buf *Dm_build_1498) { 56 | if b.buffer.Dm_build_1503() > 0 { 57 | buf.Dm_build_1535(b.buffer) 58 | } else if !b.readOver { 59 | var obj = b.obj.([]byte) 60 | buf.Dm_build_1524(obj, 0, len(obj)) 61 | b.readOver = true 62 | } 63 | } 64 | 65 | func (b *offRowBytesBinder) isReadOver() bool { 66 | return b.readOver 67 | } 68 | 69 | func (b *offRowBytesBinder) getObj() interface{} { 70 | return b.obj 71 | } 72 | 73 | type offRowBlobBinder struct { 74 | *offRowBinder 75 | } 76 | 77 | func newOffRowBlobBinder(blob DmBlob, encoding string) *offRowBlobBinder { 78 | var binder = &offRowBlobBinder{ 79 | newOffRowBinder(blob, encoding, int64(IGNORE_TARGET_LENGTH)), 80 | } 81 | binder.read(binder.buffer) 82 | binder.offRow = binder.buffer.Dm_build_1503() > Dm_build_713 83 | return binder 84 | } 85 | 86 | func (b *offRowBlobBinder) read(buf *Dm_build_1498) { 87 | if b.buffer.Dm_build_1503() > 0 { 88 | buf.Dm_build_1535(b.buffer) 89 | } else if !b.readOver { 90 | var obj = b.obj.(DmBlob) 91 | var totalLen, _ = obj.GetLength() 92 | var leaveLen = totalLen - int64(b.position) 93 | var readLen = int32(leaveLen) 94 | if leaveLen > READ_LEN { 95 | readLen = READ_LEN 96 | } 97 | var bytes, _ = obj.getBytes(int64(b.position)+1, readLen) 98 | b.position += readLen 99 | if b.position == int32(totalLen) { 100 | b.readOver = true 101 | } 102 | buf.Dm_build_1524(bytes, 0, len(bytes)) 103 | } 104 | } 105 | 106 | func (b *offRowBlobBinder) isReadOver() bool { 107 | return b.readOver 108 | } 109 | 110 | func (b *offRowBlobBinder) getObj() interface{} { 111 | return b.obj 112 | } 113 | 114 | type offRowClobBinder struct { 115 | *offRowBinder 116 | } 117 | 118 | func newOffRowClobBinder(clob DmClob, encoding string) *offRowClobBinder { 119 | var binder = &offRowClobBinder{ 120 | newOffRowBinder(clob, encoding, int64(IGNORE_TARGET_LENGTH)), 121 | } 122 | binder.read(binder.buffer) 123 | binder.offRow = binder.buffer.Dm_build_1503() > Dm_build_713 124 | return binder 125 | } 126 | 127 | func (b *offRowClobBinder) read(buf *Dm_build_1498) { 128 | if b.buffer.Dm_build_1503() > 0 { 129 | buf.Dm_build_1535(b.buffer) 130 | } else if !b.readOver { 131 | var obj = b.obj.(DmClob) 132 | var totalLen, _ = obj.GetLength() 133 | var leaveLen = totalLen - int64(b.position) 134 | var readLen = int32(leaveLen) 135 | if leaveLen > READ_LEN { 136 | readLen = READ_LEN 137 | } 138 | var str, _ = obj.getSubString(int64(b.position)+1, readLen) 139 | var bytes = Dm_build_1219.Dm_build_1432(str, b.encoding, nil) 140 | b.position += readLen 141 | if b.position == int32(totalLen) { 142 | b.readOver = true 143 | } 144 | buf.Dm_build_1524(bytes, 0, len(bytes)) 145 | } 146 | } 147 | 148 | func (b *offRowClobBinder) isReadOver() bool { 149 | return b.readOver 150 | } 151 | 152 | func (b *offRowClobBinder) getObj() interface{} { 153 | return b.obj 154 | } 155 | 156 | type offRowReaderBinder struct { 157 | *offRowBinder 158 | } 159 | 160 | func newOffRowReaderBinder(reader io.Reader, encoding string) *offRowReaderBinder { 161 | var binder = &offRowReaderBinder{ 162 | newOffRowBinder(reader, encoding, int64(IGNORE_TARGET_LENGTH)), 163 | } 164 | binder.read(binder.buffer) 165 | binder.offRow = binder.buffer.Dm_build_1503() > Dm_build_713 166 | return binder 167 | } 168 | 169 | func (b *offRowReaderBinder) read(buf *Dm_build_1498) { 170 | if b.buffer.Dm_build_1503() > 0 { 171 | buf.Dm_build_1535(b.buffer) 172 | } else if !b.readOver { 173 | var err error 174 | var readLen = READ_LEN 175 | var reader = b.obj.(io.Reader) 176 | var bytes = make([]byte, readLen) 177 | readLen, err = reader.Read(bytes) 178 | if err == io.EOF { 179 | b.readOver = true 180 | return 181 | } 182 | b.position += int32(readLen) 183 | if readLen < len(bytes) || b.targetLength != int64(IGNORE_TARGET_LENGTH) && int64(b.position) == b.targetLength { 184 | b.readOver = true 185 | } 186 | buf.Dm_build_1524(bytes[0:readLen], 0, readLen) 187 | } 188 | } 189 | 190 | func (b *offRowReaderBinder) readAll() []byte { 191 | var byteArray = Dm_build_1502() 192 | b.read(byteArray) 193 | for !b.readOver { 194 | b.read(byteArray) 195 | } 196 | return byteArray.Dm_build_1545() 197 | } 198 | 199 | func (b *offRowReaderBinder) isReadOver() bool { 200 | return b.readOver 201 | } 202 | 203 | func (b *offRowReaderBinder) getObj() interface{} { 204 | return b.obj 205 | } 206 | -------------------------------------------------------------------------------- /zv.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package dm 7 | 8 | import ( 9 | "strconv" 10 | "strings" 11 | ) 12 | 13 | type Properties struct { 14 | innerProps map[string]string 15 | } 16 | 17 | func NewProperties() *Properties { 18 | p := Properties{ 19 | innerProps: make(map[string]string, 50), 20 | } 21 | return &p 22 | } 23 | 24 | func (g *Properties) SetProperties(p *Properties) { 25 | if p == nil { 26 | return 27 | } 28 | for k, v := range p.innerProps { 29 | g.Set(strings.ToLower(k), v) 30 | } 31 | } 32 | 33 | func (g *Properties) Len() int { 34 | return len(g.innerProps) 35 | } 36 | 37 | func (g *Properties) IsNil() bool { 38 | return g == nil || g.innerProps == nil 39 | } 40 | 41 | func (g *Properties) GetString(key, def string) string { 42 | v, ok := g.innerProps[strings.ToLower(key)] 43 | 44 | if !ok || v == "" { 45 | return def 46 | } 47 | return v 48 | } 49 | 50 | func (g *Properties) GetInt(key string, def int, min int, max int) int { 51 | value, ok := g.innerProps[strings.ToLower(key)] 52 | if !ok || value == "" { 53 | return def 54 | } 55 | 56 | i, err := strconv.Atoi(value) 57 | if err != nil { 58 | return def 59 | } 60 | 61 | if i > max || i < min { 62 | return def 63 | } 64 | return i 65 | } 66 | 67 | func (g *Properties) GetBool(key string, def bool) bool { 68 | value, ok := g.innerProps[strings.ToLower(key)] 69 | if !ok || value == "" { 70 | return def 71 | } 72 | b, err := strconv.ParseBool(value) 73 | if err != nil { 74 | return def 75 | } 76 | return b 77 | } 78 | 79 | func (g *Properties) GetTrimString(key string, def string) string { 80 | value, ok := g.innerProps[strings.ToLower(key)] 81 | if !ok || value == "" { 82 | return def 83 | } else { 84 | return strings.TrimSpace(value) 85 | } 86 | } 87 | 88 | func (g *Properties) GetStringArray(key string, def []string) []string { 89 | value, ok := g.innerProps[strings.ToLower(key)] 90 | if ok || value != "" { 91 | array := strings.Split(value, ",") 92 | if len(array) > 0 { 93 | return array 94 | } 95 | } 96 | return def 97 | } 98 | 99 | //func (g *Properties) GetBool(key string) bool { 100 | // i, _ := strconv.ParseBool(g.innerProps[key]) 101 | // return i 102 | //} 103 | 104 | func (g *Properties) Set(key, value string) { 105 | g.innerProps[strings.ToLower(key)] = value 106 | } 107 | 108 | func (g *Properties) SetIfNotExist(key, value string) { 109 | if _, ok := g.innerProps[strings.ToLower(key)]; !ok { 110 | g.Set(key, value) 111 | } 112 | } 113 | 114 | // 如果p有g没有的键值对,添加进g中 115 | func (g *Properties) SetDiffProperties(p *Properties) { 116 | if p == nil { 117 | return 118 | } 119 | for k, v := range p.innerProps { 120 | if _, ok := g.innerProps[strings.ToLower(k)]; !ok { 121 | g.innerProps[strings.ToLower(k)] = v 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /zw.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package dm 7 | 8 | import ( 9 | "math/rand" 10 | "strconv" 11 | "time" 12 | 13 | "github.com/gotomicro/dmgo/util" 14 | ) 15 | 16 | var rwMap = make(map[string]*rwCounter) 17 | 18 | type rwCounter struct { 19 | ntrx_primary int64 20 | 21 | ntrx_total int64 22 | 23 | primaryPercent float64 24 | 25 | standbyPercent float64 26 | 27 | standbyNTrxMap map[string]int64 28 | 29 | standbyIdMap map[string]int32 30 | 31 | standbyCount int32 32 | 33 | flag []int32 34 | 35 | increments []int32 36 | } 37 | 38 | func newRWCounter(primaryPercent int32, standbyCount int32) *rwCounter { 39 | rwc := new(rwCounter) 40 | rwc.standbyNTrxMap = make(map[string]int64) 41 | rwc.standbyIdMap = make(map[string]int32) 42 | rwc.reset(primaryPercent, standbyCount) 43 | return rwc 44 | } 45 | 46 | func (rwc *rwCounter) reset(primaryPercent int32, standbyCount int32) { 47 | rwc.ntrx_primary = 0 48 | rwc.ntrx_total = 0 49 | rwc.standbyCount = standbyCount 50 | rwc.increments = make([]int32, standbyCount+1) 51 | rwc.flag = make([]int32, standbyCount+1) 52 | var gcd = util.GCD(primaryPercent*standbyCount, 100-primaryPercent) 53 | rwc.increments[0] = primaryPercent * standbyCount / gcd 54 | for i, tmp := 1, (100-primaryPercent)/gcd; i < len(rwc.increments); i++ { 55 | rwc.increments[i] = tmp 56 | } 57 | copy(rwc.flag, rwc.increments) 58 | 59 | if standbyCount > 0 { 60 | rwc.primaryPercent = float64(primaryPercent) / 100.0 61 | rwc.standbyPercent = float64(100-primaryPercent) / 100.0 / float64(standbyCount) 62 | } else { 63 | rwc.primaryPercent = 1 64 | rwc.standbyPercent = 0 65 | } 66 | } 67 | 68 | // 连接创建成功后调用,需要服务器返回standbyCount 69 | func getRwCounterInstance(conn *Connection, standbyCount int32) *rwCounter { 70 | key := conn.dmConnector.host + "_" + strconv.Itoa(int(conn.dmConnector.port)) + "_" + strconv.Itoa(int(conn.dmConnector.rwPercent)) 71 | 72 | rwc, ok := rwMap[key] 73 | if !ok { 74 | rwc = newRWCounter(conn.dmConnector.rwPercent, standbyCount) 75 | rwMap[key] = rwc 76 | } else if rwc.standbyCount != standbyCount { 77 | rwc.reset(conn.dmConnector.rwPercent, standbyCount) 78 | } 79 | return rwc 80 | } 81 | 82 | /** 83 | * @return 主机; 84 | */ 85 | func (rwc *rwCounter) countPrimary() RWSiteEnum { 86 | rwc.adjustNtrx() 87 | rwc.increasePrimaryNtrx() 88 | return PRIMARY 89 | } 90 | 91 | /** 92 | * @param dest 主机; 备机; any; 93 | * @return 主机; 备机 94 | */ 95 | func (rwc *rwCounter) count(dest RWSiteEnum, standby *Connection) RWSiteEnum { 96 | rwc.adjustNtrx() 97 | switch dest { 98 | case ANYSITE: 99 | { 100 | if rwc.primaryPercent == 1 || (rwc.flag[0] > rwc.getStandbyFlag(standby) && rwc.flag[0] > util.Sum(rwc.flag[1:])) { 101 | rwc.increasePrimaryNtrx() 102 | dest = PRIMARY 103 | } else { 104 | rwc.increaseStandbyNtrx(standby) 105 | dest = STANDBY 106 | } 107 | } 108 | case STANDBY: 109 | { 110 | rwc.increaseStandbyNtrx(standby) 111 | } 112 | case PRIMARY: 113 | { 114 | rwc.increasePrimaryNtrx() 115 | } 116 | } 117 | return dest 118 | } 119 | 120 | /** 121 | * 防止ntrx超出有效范围,等比调整 122 | */ 123 | func (rwc *rwCounter) adjustNtrx() { 124 | if rwc.ntrx_total >= INT64_MAX { 125 | var min int64 126 | var i = 0 127 | for _, num := range rwc.standbyNTrxMap { 128 | if i == 0 || num < min { 129 | min = num 130 | } 131 | i++ 132 | } 133 | if rwc.ntrx_primary < min { 134 | min = rwc.ntrx_primary 135 | } 136 | rwc.ntrx_primary /= min 137 | rwc.ntrx_total /= min 138 | for k, v := range rwc.standbyNTrxMap { 139 | rwc.standbyNTrxMap[k] = v / min 140 | } 141 | } 142 | 143 | if rwc.flag[0] <= 0 && util.Sum(rwc.flag[1:]) <= 0 { 144 | // 如果主库事务数以及所有备库事务数的总和 都 <= 0, 重置事务计数,给每个库的事务计数加上初始计数值 145 | for i := 0; i < len(rwc.flag); i++ { 146 | rwc.flag[i] += rwc.increments[i] 147 | } 148 | } 149 | } 150 | 151 | func (rwc *rwCounter) increasePrimaryNtrx() { 152 | rwc.ntrx_primary++ 153 | rwc.flag[0]-- 154 | rwc.ntrx_total++ 155 | } 156 | 157 | //func (rwc *rwCounter) getStandbyNtrx(standby *DmConnection) int64 { 158 | // key := standby.dmConnector.host + ":" + strconv.Itoa(int(standby.dmConnector.port)) 159 | // ret, ok := rwc.standbyNTrxMap[key] 160 | // if !ok { 161 | // ret = 0 162 | // } 163 | // 164 | // return ret 165 | //} 166 | 167 | func (rwc *rwCounter) getStandbyId(standby *Connection) int32 { 168 | key := standby.dmConnector.host + ":" + strconv.Itoa(int(standby.dmConnector.port)) 169 | sid, ok := rwc.standbyIdMap[key] 170 | if !ok { 171 | sid = int32(len(rwc.standbyIdMap) + 1) // 下标0是primary 172 | if sid > rwc.standbyCount { 173 | // 不在有效备库中 174 | return -1 175 | } 176 | rwc.standbyIdMap[key] = sid 177 | } 178 | return sid 179 | } 180 | 181 | func (rwc *rwCounter) getStandbyFlag(standby *Connection) int32 { 182 | sid := rwc.getStandbyId(standby) 183 | if sid > 0 && sid < int32(len(rwc.flag)) { 184 | // 保证备库有效 185 | return rwc.flag[sid] 186 | } 187 | return 0 188 | } 189 | 190 | func (rwc *rwCounter) increaseStandbyNtrx(standby *Connection) { 191 | key := standby.dmConnector.host + ":" + strconv.Itoa(int(standby.dmConnector.port)) 192 | ret, ok := rwc.standbyNTrxMap[key] 193 | if ok { 194 | ret += 1 195 | } else { 196 | ret = 1 197 | } 198 | rwc.standbyNTrxMap[key] = ret 199 | sid, ok := rwc.standbyIdMap[key] 200 | if !ok { 201 | sid = int32(len(rwc.standbyIdMap) + 1) // 下标0是primary 202 | rwc.standbyIdMap[key] = sid 203 | } 204 | rwc.flag[sid]-- 205 | rwc.ntrx_total++ 206 | } 207 | 208 | func (rwc *rwCounter) random(rowCount int32) int32 { 209 | rand.Seed(time.Now().UnixNano()) 210 | if rowCount > rwc.standbyCount { 211 | return rand.Int31n(rwc.standbyCount) 212 | } else { 213 | return rand.Int31n(rowCount) 214 | } 215 | } 216 | 217 | func (rwc *rwCounter) String() string { 218 | return "PERCENT(P/S) : " + strconv.FormatFloat(rwc.primaryPercent, 'f', -1, 64) + "/" + strconv.FormatFloat(rwc.standbyPercent, 'f', -1, 64) + "\nNTRX_PRIMARY : " + 219 | strconv.FormatInt(rwc.ntrx_primary, 10) + "\nNTRX_TOTAL : " + strconv.FormatInt(rwc.ntrx_total, 10) + "\nNTRX_STANDBY : " 220 | } 221 | -------------------------------------------------------------------------------- /zzj.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package dm 7 | 8 | import "database/sql/driver" 9 | 10 | var SQLName sqlName 11 | 12 | type sqlName struct { 13 | m_name string // 描述对象自身名称, 14 | 15 | // 若为内置类型,则表示数据库端定义的名称,与dType相对应 16 | m_pkgName string // 所在包的名称,适用于包中类型的定义 17 | 18 | m_schName string // 描述对象所在模式名 19 | 20 | m_fulName string // 描述对象完全限定名, 记录用户发送的名称信息; 21 | 22 | // 以及接受服务器响应后,拼成的名称信息 23 | 24 | m_schId int // 保存模式id,模式名无法传出,利用模式id查找 25 | 26 | m_packId int // 保存包的id,包名无法传出,用于查找包名 27 | 28 | m_conn *Connection 29 | } 30 | 31 | func (SqlName *sqlName) init() { 32 | SqlName.m_name = "" 33 | SqlName.m_pkgName = "" 34 | SqlName.m_schName = "" 35 | SqlName.m_fulName = "" 36 | SqlName.m_schId = -1 37 | SqlName.m_packId = -1 38 | SqlName.m_conn = nil 39 | } 40 | 41 | func newSqlNameByFulName(fulName string) *sqlName { 42 | o := new(sqlName) 43 | o.init() 44 | o.m_fulName = fulName 45 | return o 46 | } 47 | 48 | func newSqlNameByConn(conn *Connection) *sqlName { 49 | o := new(sqlName) 50 | o.init() 51 | o.m_conn = conn 52 | return o 53 | } 54 | 55 | func (SqlName *sqlName) getFulName() (string, error) { 56 | // 说明非内嵌式数据类型名称描述信息传入或已经获取过描述信息 57 | if len(SqlName.m_fulName) > 0 { 58 | return SqlName.m_fulName, nil 59 | } 60 | 61 | // 内嵌式数据类型无名称描述信息返回,直接返回null 62 | if SqlName.m_name == "" { 63 | // DBError.throwUnsupportedSQLException(); 64 | return "", nil 65 | } 66 | 67 | // 其他数据名描述信息 68 | if SqlName.m_packId != 0 || SqlName.m_schId != 0 { 69 | sql := "SELECT NAME INTO ? FROM SYS.SYSOBJECTS WHERE ID=?" 70 | 71 | params := make([]driver.Value, 2) 72 | var v string 73 | params[0] = &v 74 | if SqlName.m_packId != 0 { 75 | params[1] = SqlName.m_packId 76 | } else { 77 | params[1] = SqlName.m_schId 78 | } 79 | 80 | rs, err := SqlName.m_conn.query(sql, params) 81 | if err != nil { 82 | return "", err 83 | } 84 | rs.close() 85 | 86 | // 说明是包中定义的对象 87 | if SqlName.m_packId != 0 { 88 | // pkg全名 89 | SqlName.m_pkgName = v 90 | SqlName.m_fulName = SqlName.m_pkgName + "." + SqlName.m_name 91 | } else { 92 | // 非包中定义的对象 93 | // schema 名称 94 | SqlName.m_schName = v 95 | SqlName.m_fulName = SqlName.m_schName + "." + SqlName.m_name 96 | } 97 | } 98 | // 将有效值返回 99 | if len(SqlName.m_fulName) > 0 { 100 | return SqlName.m_fulName, nil 101 | } else { 102 | return SqlName.m_name, nil 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /zzk.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | package dm 6 | 7 | import ( 8 | "bytes" 9 | "strconv" 10 | "strings" 11 | 12 | "github.com/gotomicro/dmgo/parser" 13 | 14 | "github.com/gotomicro/dmgo/util" 15 | ) 16 | 17 | func (dmConn *Connection) lex(sql string) ([]*parser.LVal, error) { 18 | if dmConn.lexer == nil { 19 | dmConn.lexer = parser.NewLexer(strings.NewReader(sql), false) 20 | } else { 21 | dmConn.lexer.Reset(strings.NewReader(sql)) 22 | } 23 | 24 | lexer := dmConn.lexer 25 | var lval *parser.LVal 26 | var err error 27 | lvalList := make([]*parser.LVal, 0, 64) 28 | lval, err = lexer.Yylex() 29 | if err != nil { 30 | return nil, err 31 | } 32 | 33 | for lval != nil { 34 | lvalList = append(lvalList, lval) 35 | lval.Position = len(lvalList) 36 | lval, err = lexer.Yylex() 37 | if err != nil { 38 | return nil, err 39 | } 40 | } 41 | 42 | return lvalList, nil 43 | } 44 | 45 | func lexSkipWhitespace(sql string, n int) ([]*parser.LVal, error) { 46 | lexer := parser.NewLexer(strings.NewReader(sql), false) 47 | 48 | var lval *parser.LVal 49 | var err error 50 | lvalList := make([]*parser.LVal, 0, 64) 51 | lval, err = lexer.Yylex() 52 | if err != nil { 53 | return nil, err 54 | } 55 | 56 | for lval != nil && n > 0 { 57 | lval.Position = len(lvalList) 58 | if lval.Tp == parser.WHITESPACE_OR_COMMENT { 59 | continue 60 | } 61 | 62 | lvalList = append(lvalList, lval) 63 | n-- 64 | lval, err = lexer.Yylex() 65 | if err != nil { 66 | return nil, err 67 | } 68 | 69 | } 70 | 71 | return lvalList, nil 72 | } 73 | 74 | func (dmConn *Connection) escape(sql string, keywords []string) (string, error) { 75 | 76 | if (keywords == nil || len(keywords) == 0) && strings.Index(sql, "{") == -1 { 77 | return sql, nil 78 | } 79 | var keywordMap map[string]interface{} 80 | if keywords != nil && len(keywords) > 0 { 81 | keywordMap = make(map[string]interface{}, len(keywords)) 82 | for _, keyword := range keywords { 83 | keywordMap[strings.ToUpper(keyword)] = nil 84 | } 85 | } 86 | nsql := bytes.NewBufferString("") 87 | stack := make([]bool, 0, 64) 88 | lvalList, err := dmConn.lex(sql) 89 | if err != nil { 90 | return "", err 91 | } 92 | 93 | for i := 0; i < len(lvalList); i++ { 94 | lval0 := lvalList[i] 95 | if lval0.Tp == parser.NORMAL { 96 | if lval0.Value == "{" { 97 | lval1 := next(lvalList, i+1) 98 | if lval1 == nil || lval1.Tp != parser.NORMAL { 99 | stack = append(stack, false) 100 | nsql.WriteString(lval0.Value) 101 | } else if util.StringUtil.EqualsIgnoreCase(lval1.Value, "escape") || util.StringUtil.EqualsIgnoreCase(lval1.Value, "call") { 102 | stack = append(stack, true) 103 | } else if util.StringUtil.EqualsIgnoreCase(lval1.Value, "oj") { 104 | stack = append(stack, true) 105 | lval1.Value = "" 106 | lval1.Tp = parser.WHITESPACE_OR_COMMENT 107 | } else if util.StringUtil.EqualsIgnoreCase(lval1.Value, "d") { 108 | stack = append(stack, true) 109 | lval1.Value = "date" 110 | } else if util.StringUtil.EqualsIgnoreCase(lval1.Value, "t") { 111 | stack = append(stack, true) 112 | lval1.Value = "time" 113 | } else if util.StringUtil.EqualsIgnoreCase(lval1.Value, "ts") { 114 | stack = append(stack, true) 115 | lval1.Value = "datetime" 116 | } else if util.StringUtil.EqualsIgnoreCase(lval1.Value, "fn") { 117 | stack = append(stack, true) 118 | lval1.Value = "" 119 | lval1.Tp = parser.WHITESPACE_OR_COMMENT 120 | lval2 := next(lvalList, lval1.Position+1) 121 | if lval2 != nil && lval2.Tp == parser.NORMAL && util.StringUtil.EqualsIgnoreCase(lval2.Value, "database") { 122 | lval2.Value = "cur_database" 123 | } 124 | } else if util.StringUtil.Equals(lval1.Value, "?") { 125 | lval2 := next(lvalList, lval1.Position+1) 126 | if lval2 != nil && lval2.Tp == parser.NORMAL && util.StringUtil.EqualsIgnoreCase(lval2.Value, "=") { 127 | lval3 := next(lvalList, lval2.Position+1) 128 | if lval3 != nil && lval3.Tp == parser.NORMAL && util.StringUtil.EqualsIgnoreCase(lval3.Value, "call") { 129 | stack = append(stack, true) 130 | lval3.Value = "" 131 | lval3.Tp = parser.WHITESPACE_OR_COMMENT 132 | } else { 133 | stack = append(stack, false) 134 | nsql.WriteString(lval0.Value) 135 | } 136 | } else { 137 | stack = append(stack, false) 138 | nsql.WriteString(lval0.Value) 139 | } 140 | } else { 141 | stack = append(stack, false) 142 | nsql.WriteString(lval0.Value) 143 | } 144 | } else if util.StringUtil.Equals(lval0.Value, "}") { 145 | if len(stack) != 0 && stack[len(stack)-1] { 146 | 147 | } else { 148 | nsql.WriteString(lval0.Value) 149 | } 150 | stack = stack[:len(stack)-1] 151 | } else { 152 | if keywordMap != nil { 153 | _, ok := keywordMap[strings.ToUpper(lval0.Value)] 154 | if ok { 155 | nsql.WriteString("\"" + util.StringUtil.ProcessDoubleQuoteOfName(strings.ToUpper(lval0.Value)) + "\"") 156 | } else { 157 | nsql.WriteString(lval0.Value) 158 | } 159 | } else { 160 | nsql.WriteString(lval0.Value) 161 | } 162 | } 163 | } else if lval0.Tp == parser.STRING { 164 | nsql.WriteString("'" + util.StringUtil.ProcessSingleQuoteOfName(lval0.Value) + "'") 165 | } else { 166 | nsql.WriteString(lval0.Value) 167 | } 168 | } 169 | 170 | return nsql.String(), nil 171 | } 172 | 173 | func next(lvalList []*parser.LVal, start int) *parser.LVal { 174 | var lval *parser.LVal 175 | 176 | size := len(lvalList) 177 | for i := start; i < size; i++ { 178 | lval = lvalList[i] 179 | if lval.Tp != parser.WHITESPACE_OR_COMMENT { 180 | break 181 | } 182 | } 183 | return lval 184 | } 185 | 186 | func (dmConn *Connection) execOpt(sql string, optParamList []OptParameter, serverEncoding string) (string, []OptParameter, error) { 187 | nsql := bytes.NewBufferString("") 188 | 189 | lvalList, err := dmConn.lex(sql) 190 | if err != nil { 191 | return "", optParamList, err 192 | } 193 | 194 | if nil == lvalList || len(lvalList) == 0 { 195 | return sql, optParamList, nil 196 | } 197 | 198 | firstWord := lvalList[0].Value 199 | if !(util.StringUtil.EqualsIgnoreCase(firstWord, "INSERT") || util.StringUtil.EqualsIgnoreCase(firstWord, "SELECT") || 200 | util.StringUtil.EqualsIgnoreCase(firstWord, "UPDATE") || util.StringUtil.EqualsIgnoreCase(firstWord, "DELETE")) { 201 | return sql, optParamList, nil 202 | } 203 | 204 | breakIndex := 0 205 | for i := 0; i < len(lvalList); i++ { 206 | lval := lvalList[i] 207 | switch lval.Tp { 208 | case parser.NULL: 209 | { 210 | nsql.WriteString("?") 211 | optParamList = append(optParamList, newOptParameter(nil, NULL, NULL_PREC)) 212 | } 213 | case parser.INT: 214 | { 215 | nsql.WriteString("?") 216 | value, err := strconv.Atoi(lval.Value) 217 | if err != nil { 218 | return "", optParamList, err 219 | } 220 | 221 | if value <= int(INT32_MAX) && value >= int(INT32_MIN) { 222 | optParamList = append(optParamList, newOptParameter(G2DB.toInt32(int32(value)), INT, INT_PREC)) 223 | 224 | } else { 225 | optParamList = append(optParamList, newOptParameter(G2DB.toInt64(int64(value)), BIGINT, BIGINT_PREC)) 226 | } 227 | } 228 | case parser.DOUBLE: 229 | { 230 | nsql.WriteString("?") 231 | f, err := strconv.ParseFloat(lval.Value, 64) 232 | if err != nil { 233 | return "", optParamList, err 234 | } 235 | 236 | optParamList = append(optParamList, newOptParameter(G2DB.toFloat64(f), DOUBLE, DOUBLE_PREC)) 237 | } 238 | case parser.DECIMAL: 239 | { 240 | nsql.WriteString("?") 241 | bytes, err := G2DB.toDecimal(lval.Value, 0, 0) 242 | if err != nil { 243 | return "", optParamList, err 244 | } 245 | optParamList = append(optParamList, newOptParameter(bytes, DECIMAL, 0)) 246 | } 247 | case parser.STRING: 248 | { 249 | 250 | if len(lval.Value) > int(INT16_MAX) { 251 | 252 | nsql.WriteString("'" + util.StringUtil.ProcessSingleQuoteOfName(lval.Value) + "'") 253 | } else { 254 | nsql.WriteString("?") 255 | optParamList = append(optParamList, newOptParameter(Dm_build_1219.Dm_build_1432(lval.Value, serverEncoding, dmConn), VARCHAR, VARCHAR_PREC)) 256 | } 257 | } 258 | case parser.HEX_INT: 259 | 260 | nsql.WriteString(lval.Value) 261 | default: 262 | 263 | nsql.WriteString(lval.Value) 264 | } 265 | 266 | if breakIndex > 0 { 267 | break 268 | } 269 | } 270 | 271 | if breakIndex > 0 { 272 | for i := breakIndex + 1; i < len(lvalList); i++ { 273 | nsql.WriteString(lvalList[i].Value) 274 | } 275 | } 276 | 277 | return nsql.String(), optParamList, nil 278 | } 279 | 280 | func (dmConn *Connection) hasConst(sql string) (bool, error) { 281 | lvalList, err := dmConn.lex(sql) 282 | if err != nil { 283 | return false, err 284 | } 285 | 286 | if nil == lvalList || len(lvalList) == 0 { 287 | return false, nil 288 | } 289 | 290 | for i := 0; i < len(lvalList); i++ { 291 | switch lvalList[i].Tp { 292 | case parser.NULL, parser.INT, parser.DOUBLE, parser.DECIMAL, parser.STRING, parser.HEX_INT: 293 | return true, nil 294 | } 295 | } 296 | return false, nil 297 | } 298 | 299 | type OptParameter struct { 300 | bytes []byte 301 | ioType byte 302 | tp int 303 | prec int 304 | scale int 305 | } 306 | 307 | func newOptParameter(bytes []byte, tp int, prec int) OptParameter { 308 | o := new(OptParameter) 309 | o.bytes = bytes 310 | o.tp = tp 311 | o.prec = prec 312 | return *o 313 | } 314 | 315 | func (parameter *OptParameter) String() string { 316 | if parameter.bytes == nil { 317 | return "" 318 | } 319 | return string(parameter.bytes) 320 | } 321 | -------------------------------------------------------------------------------- /zzl.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package dm 7 | 8 | type StructDescriptor struct { 9 | m_typeDesc *TypeDescriptor 10 | } 11 | 12 | func newStructDescriptor(fulName string, conn *Connection) (*StructDescriptor, error) { 13 | sd := new(StructDescriptor) 14 | if fulName == "" { 15 | return nil, ECGO_INVALID_COMPLEX_TYPE_NAME.throw() 16 | } 17 | 18 | sd.m_typeDesc = newTypeDescriptorWithFulName(fulName, conn) 19 | 20 | err := sd.m_typeDesc.parseDescByName() 21 | if err != nil { 22 | return nil, err 23 | } 24 | 25 | return sd, nil 26 | } 27 | 28 | func newStructDescriptorByTypeDescriptor(desc *TypeDescriptor) *StructDescriptor { 29 | sd := new(StructDescriptor) 30 | sd.m_typeDesc = desc 31 | return sd 32 | } 33 | 34 | func (sd *StructDescriptor) getSize() int { 35 | return sd.m_typeDesc.m_size 36 | } 37 | 38 | func (sd *StructDescriptor) getObjId() int { 39 | return sd.m_typeDesc.m_objId 40 | } 41 | 42 | func (sd *StructDescriptor) getItemsDesc() []TypeDescriptor { 43 | return sd.m_typeDesc.m_fieldsObj 44 | } 45 | -------------------------------------------------------------------------------- /zzm.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | 6 | package dm 7 | 8 | import ( 9 | "os" 10 | 11 | "github.com/gotomicro/dmgo/util" 12 | ) 13 | 14 | var LogDirDef, _ = os.Getwd() 15 | 16 | var StatDirDef, _ = os.Getwd() 17 | 18 | const ( 19 | DEFAULT_PORT int32 = 5236 20 | 21 | //log level 22 | LOG_OFF int = 0 23 | 24 | LOG_ERROR int = 1 25 | 26 | LOG_WARN int = 2 27 | 28 | LOG_SQL int = 3 29 | 30 | LOG_INFO int = 4 31 | 32 | LOG_DEBUG int = 5 33 | 34 | LOG_ALL int = 9 35 | 36 | //stat 37 | STAT_SQL_REMOVE_LATEST int = 0 38 | 39 | STAT_SQL_REMOVE_OLDEST int = 1 40 | 41 | // 编码字符集 42 | ENCODING_UTF8 string = "UTF-8" 43 | 44 | ENCODING_EUCKR string = "EUC-KR" 45 | 46 | ENCODING_GB18030 string = "GB18030" 47 | 48 | DbAliveCheckFreqDef = 0 49 | 50 | LocaleDef = 0 51 | 52 | // log 53 | LogLevelDef = LOG_OFF // 日志级别:off, error, warn, sql, info, all 54 | 55 | LogFlushFreqDef = 10 // 日志刷盘时间s (>=0) 56 | 57 | LogFlushQueueSizeDef = 100 //日志队列大小 58 | 59 | LogBufferSizeDef = 32 * 1024 // 日志缓冲区大小 (>0) 60 | 61 | // stat 62 | StatEnableDef = false // 63 | 64 | StatFlushFreqDef = 3 // 日志刷盘时间s (>=0) 65 | 66 | StatSlowSqlCountDef = 100 // 慢sql top行数,(0-1000) 67 | 68 | StatHighFreqSqlCountDef = 100 // 高频sql top行数, (0-1000) 69 | 70 | StatSqlMaxCountDef = 100000 // sql 统计最大值(0-100000) 71 | 72 | StatSqlRemoveModeDef = STAT_SQL_REMOVE_LATEST // 记录sql数超过最大值时,sql淘汰方式 73 | ) 74 | 75 | var ( 76 | DbAliveCheckFreq = DbAliveCheckFreqDef 77 | 78 | Locale = LocaleDef // 0:简体中文 1:英文 2:繁体中文 79 | 80 | // log 81 | LogLevel = LogLevelDef // 日志级别:off, error, warn, sql, info, all 82 | 83 | LogDir = LogDirDef 84 | 85 | LogFlushFreq = LogFlushFreqDef // 日志刷盘时间s (>=0) 86 | 87 | LogFlushQueueSize = LogFlushQueueSizeDef 88 | 89 | LogBufferSize = LogBufferSizeDef // 日志缓冲区大小 (>0) 90 | 91 | // stat 92 | StatEnable = StatEnableDef // 93 | 94 | StatDir = StatDirDef // jdbc工作目录,所有生成的文件都在该目录下 95 | 96 | StatFlushFreq = StatFlushFreqDef // 日志刷盘时间s (>=0) 97 | 98 | StatSlowSqlCount = StatSlowSqlCountDef // 慢sql top行数,(0-1000) 99 | 100 | StatHighFreqSqlCount = StatHighFreqSqlCountDef // 高频sql top行数, (0-1000) 101 | 102 | StatSqlMaxCount = StatSqlMaxCountDef // sql 统计最大值(0-100000) 103 | 104 | StatSqlRemoveMode = StatSqlRemoveModeDef // 记录sql数超过最大值时,sql淘汰方式 105 | 106 | /*---------------------------------------------------------------*/ 107 | ServerGroupMap = make(map[string]*epGroup) 108 | ) 109 | 110 | func ParseLogLevel(props *Properties) int { 111 | logLevel := LOG_OFF 112 | value := props.GetString(LogLevelKey, "") 113 | if value != "" && !util.StringUtil.IsDigit(value) { 114 | if util.StringUtil.EqualsIgnoreCase("debug", value) { 115 | logLevel = LOG_DEBUG 116 | } else if util.StringUtil.EqualsIgnoreCase("info", value) { 117 | logLevel = LOG_INFO 118 | } else if util.StringUtil.EqualsIgnoreCase("sql", value) { 119 | logLevel = LOG_SQL 120 | } else if util.StringUtil.EqualsIgnoreCase("warn", value) { 121 | logLevel = LOG_WARN 122 | } else if util.StringUtil.EqualsIgnoreCase("error", value) { 123 | logLevel = LOG_ERROR 124 | } else if util.StringUtil.EqualsIgnoreCase("off", value) { 125 | logLevel = LOG_OFF 126 | } else if util.StringUtil.EqualsIgnoreCase("all", value) { 127 | logLevel = LOG_ALL 128 | } 129 | } else { 130 | logLevel = props.GetInt(LogLevelKey, logLevel, LOG_OFF, LOG_INFO) 131 | } 132 | 133 | return logLevel 134 | } 135 | -------------------------------------------------------------------------------- /zzn.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 | * All rights reserved. 4 | */ 5 | package dm 6 | 7 | import ( 8 | "database/sql" 9 | "database/sql/driver" 10 | "math" 11 | "reflect" 12 | "strings" 13 | "time" 14 | ) 15 | 16 | const ( 17 | INT8_MAX int8 = math.MaxInt8 18 | 19 | INT8_MIN int8 = math.MinInt8 20 | 21 | BYTE_MAX byte = math.MaxUint8 22 | 23 | BYTE_MIN byte = 0 24 | 25 | INT16_MAX int16 = math.MaxInt16 26 | 27 | INT16_MIN int16 = math.MinInt16 28 | 29 | UINT16_MAX uint16 = math.MaxUint16 30 | 31 | UINT16_MIN uint16 = 0 32 | 33 | INT32_MAX int32 = math.MaxInt32 34 | 35 | INT32_MIN int32 = math.MinInt32 36 | 37 | UINT32_MAX uint32 = math.MaxUint32 38 | 39 | UINT32_MIN uint32 = 0 40 | 41 | INT64_MAX int64 = math.MaxInt64 42 | 43 | INT64_MIN int64 = math.MinInt64 44 | 45 | UINT64_MAX uint64 = math.MaxUint64 46 | 47 | UINT64_MIN uint64 = 0 48 | 49 | FLOAT32_MAX float32 = 3.4e+38 50 | 51 | FLOAT32_MIN float32 = -3.4e+38 52 | 53 | BYTE_SIZE = 1 54 | 55 | USINT_SIZE = 2 56 | 57 | ULINT_SIZE = 4 58 | 59 | DDWORD_SIZE = 8 60 | 61 | LINT64_SIZE = 8 62 | 63 | CHAR = 0 64 | 65 | VARCHAR2 = 1 66 | 67 | VARCHAR = 2 68 | 69 | BIT = 3 70 | 71 | TINYINT = 5 72 | 73 | SMALLINT = 6 74 | 75 | INT = 7 76 | 77 | BIGINT = 8 78 | 79 | DECIMAL = 9 80 | 81 | REAL = 10 82 | 83 | DOUBLE = 11 84 | 85 | BLOB = 12 86 | 87 | BOOLEAN = 13 88 | 89 | DATE = 14 90 | 91 | TIME = 15 92 | 93 | DATETIME = 16 94 | 95 | BINARY = 17 96 | 97 | VARBINARY = 18 98 | 99 | CLOB = 19 100 | 101 | INTERVAL_YM = 20 102 | 103 | INTERVAL_DT = 21 104 | 105 | TIME_TZ = 22 106 | 107 | DATETIME_TZ = 23 108 | 109 | NULL = 25 110 | 111 | ANY = 31 112 | 113 | STAR_ALL = 32 114 | 115 | STAR = 33 116 | 117 | RECORD = 40 118 | 119 | TYPE = 41 120 | 121 | TYPE_REF = 42 122 | 123 | UNKNOWN = 54 124 | 125 | ARRAY = 117 126 | 127 | CLASS = 119 128 | 129 | CURSOR = 120 130 | 131 | PLTYPE_RECORD = 121 132 | 133 | SARRAY = 122 134 | 135 | CURSOR_ORACLE = -10 136 | 137 | BIT_PREC = BYTE_SIZE 138 | 139 | TINYINT_PREC = BYTE_SIZE 140 | 141 | SMALLINT_PREC = USINT_SIZE 142 | 143 | INT_PREC = ULINT_SIZE 144 | 145 | BIGINT_PREC = LINT64_SIZE 146 | 147 | REAL_PREC = 4 148 | 149 | DOUBLE_PREC = 8 150 | 151 | DATE_PREC = 3 152 | 153 | TIME_PREC = 5 154 | 155 | DATETIME_PREC = 8 156 | 157 | INTERVAL_YM_PREC = 3 * ULINT_SIZE 158 | 159 | INTERVAL_DT_PREC = 6 * ULINT_SIZE 160 | 161 | TIME_TZ_PREC = 12 162 | 163 | DATETIME_TZ_PREC = 12 164 | 165 | VARCHAR_PREC = 8188 166 | 167 | VARBINARY_PREC = 8188 168 | 169 | BLOB_PREC int32 = INT32_MAX 170 | 171 | CLOB_PREC int32 = INT32_MAX 172 | 173 | NULL_PREC = 0 174 | 175 | LOCAL_TIME_ZONE_SCALE_MASK = 0x00001000 176 | 177 | BFILE_PREC = 512 178 | 179 | BFILE_SCALE = 6 180 | 181 | COMPLEX_SCALE = 5 182 | 183 | CURRENCY_PREC = 19 184 | 185 | CURRENCY_SCALE = 4 186 | 187 | FLOAT_SCALE_MASK = 0x81 188 | ) 189 | 190 | func resetColType(stmt *DmStatement, i int, colType int32) bool { 191 | 192 | parameter := &stmt.params[i] 193 | 194 | if parameter.ioType == IO_TYPE_OUT { 195 | stmt.curRowBindIndicator[i] |= BIND_OUT 196 | return false 197 | } else if parameter.ioType == IO_TYPE_IN { 198 | stmt.curRowBindIndicator[i] |= BIND_IN 199 | } else { 200 | stmt.curRowBindIndicator[i] |= BIND_IN 201 | stmt.curRowBindIndicator[i] |= BIND_OUT 202 | } 203 | 204 | if parameter.typeFlag != TYPE_FLAG_EXACT { 205 | 206 | parameter.colType = colType 207 | parameter.scale = 0 208 | switch colType { 209 | case CHAR, VARCHAR, VARCHAR2: 210 | parameter.prec = VARCHAR_PREC 211 | case CLOB: 212 | parameter.prec = CLOB_PREC 213 | case BINARY, VARBINARY: 214 | parameter.prec = VARBINARY_PREC 215 | case BLOB: 216 | parameter.prec = BLOB_PREC 217 | case BOOLEAN, BIT: 218 | parameter.prec = BIT_PREC 219 | } 220 | } 221 | 222 | return true 223 | } 224 | 225 | func isBFile(colType int, prec int, scale int) bool { 226 | return colType == VARCHAR && prec == BFILE_PREC && scale == BFILE_SCALE 227 | } 228 | 229 | func isComplexType(colType int, scale int) bool { 230 | return (colType == BLOB && scale == COMPLEX_SCALE) || colType == ARRAY || colType == SARRAY || colType == CLASS || colType == PLTYPE_RECORD 231 | } 232 | 233 | func isLocalTimeZone(colType int, scale int) bool { 234 | return colType == DATETIME && (scale&LOCAL_TIME_ZONE_SCALE_MASK) != 0 235 | } 236 | 237 | func getLocalTimeZoneScale(colType int, scale int) int { 238 | return scale & (^LOCAL_TIME_ZONE_SCALE_MASK) 239 | } 240 | 241 | func isFloat(colType int, scale int) bool { 242 | return colType == DECIMAL && scale == FLOAT_SCALE_MASK 243 | } 244 | 245 | func getFloatPrec(prec int) int { 246 | return int(math.Round(float64(prec)*0.30103)) + 1 247 | } 248 | 249 | func getFloatScale(scale int) int { 250 | return scale & (^FLOAT_SCALE_MASK) 251 | } 252 | 253 | var ( 254 | scanTypeFloat32 = reflect.TypeOf(float32(0)) 255 | scanTypeFloat64 = reflect.TypeOf(float64(0)) 256 | scanTypeBool = reflect.TypeOf(false) 257 | scanTypeInt8 = reflect.TypeOf(int8(0)) 258 | scanTypeInt16 = reflect.TypeOf(int16(0)) 259 | scanTypeInt32 = reflect.TypeOf(int32(0)) 260 | scanTypeInt64 = reflect.TypeOf(int64(0)) 261 | scanTypeNullBool = reflect.TypeOf(sql.NullBool{}) 262 | scanTypeNullFloat = reflect.TypeOf(sql.NullFloat64{}) 263 | scanTypeNullInt = reflect.TypeOf(sql.NullInt64{}) 264 | scanTypeNullString = reflect.TypeOf(sql.NullString{}) 265 | scanTypeNullTime = reflect.TypeOf(sql.NullTime{}) 266 | scanTypeRawBytes = reflect.TypeOf(sql.RawBytes{}) 267 | scanTypeString = reflect.TypeOf("") 268 | scanTypeTime = reflect.TypeOf(time.Now()) 269 | scanTypeUnknown = reflect.TypeOf(new(interface{})) 270 | ) 271 | 272 | func (column *column) ScanType() reflect.Type { 273 | 274 | switch column.colType { 275 | case BOOLEAN: 276 | if column.nullable { 277 | return scanTypeNullBool 278 | } 279 | 280 | return scanTypeBool 281 | 282 | case BIT: 283 | if strings.ToLower(column.typeName) == "boolean" { 284 | 285 | if column.nullable { 286 | return scanTypeNullBool 287 | } 288 | 289 | return scanTypeBool 290 | } else { 291 | 292 | if column.nullable { 293 | return scanTypeNullInt 294 | } 295 | return scanTypeInt8 296 | } 297 | 298 | case TINYINT: 299 | if column.nullable { 300 | return scanTypeNullInt 301 | } 302 | return scanTypeInt8 303 | 304 | case SMALLINT: 305 | if column.nullable { 306 | return scanTypeNullInt 307 | } 308 | return scanTypeInt16 309 | 310 | case INT: 311 | if column.nullable { 312 | return scanTypeNullInt 313 | } 314 | 315 | return scanTypeInt32 316 | 317 | case BIGINT: 318 | if column.nullable { 319 | return scanTypeNullInt 320 | } 321 | return scanTypeInt64 322 | 323 | case REAL: 324 | if column.nullable { 325 | return scanTypeNullFloat 326 | } 327 | 328 | return scanTypeFloat32 329 | 330 | case DOUBLE: 331 | 332 | if strings.ToLower(column.typeName) == "float" { 333 | if column.nullable { 334 | return scanTypeNullFloat 335 | } 336 | 337 | return scanTypeFloat32 338 | } 339 | 340 | if column.nullable { 341 | return scanTypeNullFloat 342 | } 343 | 344 | return scanTypeFloat64 345 | case DATE, TIME, DATETIME: 346 | if column.nullable { 347 | return scanTypeNullTime 348 | } 349 | 350 | return scanTypeTime 351 | 352 | case DECIMAL, BINARY, VARBINARY, BLOB: 353 | return scanTypeRawBytes 354 | 355 | case CHAR, VARCHAR2, VARCHAR, CLOB: 356 | if column.nullable { 357 | return scanTypeNullString 358 | } 359 | return scanTypeString 360 | } 361 | 362 | return scanTypeUnknown 363 | } 364 | 365 | func (column *column) Length() (length int64, ok bool) { 366 | 367 | switch column.colType { 368 | case BINARY: 369 | case VARBINARY: 370 | case BLOB: 371 | case CHAR: 372 | case VARCHAR2: 373 | case VARCHAR: 374 | case CLOB: 375 | return int64(column.prec), true 376 | } 377 | 378 | return int64(0), false 379 | } 380 | 381 | func (column *column) PrecisionScale() (precision, scale int64, ok bool) { 382 | switch column.colType { 383 | case DECIMAL: 384 | return int64(column.prec), int64(column.scale), true 385 | } 386 | 387 | return int64(0), int64(0), false 388 | } 389 | 390 | func (column *column) getColumnData(bytes []byte, conn *Connection) (driver.Value, error) { 391 | if bytes == nil { 392 | return nil, nil 393 | } 394 | 395 | switch column.colType { 396 | case BOOLEAN: 397 | return bytes[0] != 0, nil 398 | case BIT: 399 | if strings.ToLower(column.typeName) == "boolean" { 400 | return bytes[0] != 0, nil 401 | } 402 | 403 | return int8(bytes[0]), nil 404 | case TINYINT: 405 | return int8(bytes[0]), nil 406 | case SMALLINT: 407 | return Dm_build_1219.Dm_build_1316(bytes, 0), nil 408 | case INT: 409 | return Dm_build_1219.Dm_build_1321(bytes, 0), nil 410 | case BIGINT: 411 | return Dm_build_1219.Dm_build_1326(bytes, 0), nil 412 | case REAL: 413 | return Dm_build_1219.Dm_build_1331(bytes, 0), nil 414 | case DOUBLE: 415 | 416 | return Dm_build_1219.Dm_build_1335(bytes, 0), nil 417 | case DATE, TIME, DATETIME, TIME_TZ, DATETIME_TZ: 418 | return DB2G.toTime(bytes, column, conn) 419 | case INTERVAL_DT: 420 | return newDmIntervalDTByBytes(bytes).String(), nil 421 | case INTERVAL_YM: 422 | return newDmIntervalYMByBytes(bytes).String(), nil 423 | case DECIMAL: 424 | tmp, err := DB2G.toDmDecimal(bytes, column, conn) 425 | if err != nil { 426 | return nil, err 427 | } 428 | return tmp.String(), nil 429 | 430 | case BINARY, VARBINARY: 431 | return bytes, nil 432 | case BLOB: 433 | return DB2G.toDmBlob(bytes, column, conn), nil 434 | case CHAR, VARCHAR2, VARCHAR: 435 | return Dm_build_1219.Dm_build_1376(bytes, 0, len(bytes), conn.getServerEncoding(), conn), nil 436 | case CLOB: 437 | return DB2G.toDmClob(bytes, conn, column), nil 438 | } 439 | 440 | return string(bytes), nil 441 | } 442 | 443 | func emptyStringToNil(t int32) bool { 444 | switch t { 445 | case BOOLEAN, BIT, TINYINT, SMALLINT, INT, BIGINT, REAL, DOUBLE, DECIMAL, 446 | DATE, TIME, DATETIME, INTERVAL_DT, INTERVAL_YM, TIME_TZ, DATETIME_TZ: 447 | return true 448 | default: 449 | return false 450 | } 451 | } 452 | --------------------------------------------------------------------------------