feat(db): 添加对达梦数据库的支持

- 在应用程序中新增对达梦数据库(DM)的配置和连接支持
- 实现 SetDmDB 函数以配置达梦数据库连接
- 更新数据库操作逻辑,支持达梦特有的 SQL 语法和功能
- 在相关文件中添加达梦数据库的处理逻辑,包括表创建、数据插入和查询
- 更新 go.mod 和 go.sum 文件以引入达梦数据库驱动
- 增强文档,详细说明达梦数据库的配置和使用方法
This commit is contained in:
2026-03-20 10:46:51 +08:00
parent 7ab803c5cc
commit b43f968b6c
194 changed files with 211502 additions and 2328 deletions
+43
View File
@@ -0,0 +1,43 @@
# Change Logs
*你可以在文件p.go中的发版标记里找到当前驱动的svn号
## svn 31633
修复了带ipv6地址的服务名无法连接数据库的问题
dm.DmError输出不再附加堆栈信息,如需要则调用dm.DmError.Stack()方法单独获取
服务器开启常量参数化优化时,go驱动出现一些报错问题
## svn 16752
支持在连接串上直接配置动态服务名,使用示例:
dm://user:password@GroupName?GroupName=(host1:port1,host2:port2,...)
## svn 16505
新增连接串属性driverReconnect,配合doSwitch=1或2使用,表示连接重连是否使用驱动自身的重连机制,否则在连接失效时返回sql标准错误driver.ErrBadConn,由go来处理重连
## svn 16258
重连逻辑修改,当连接失效时,返回driver.ErrBadConn而不是驱动自己管理重连,连接串参数doSwitch默认值改为1
驱动接口方法同步锁改到连接网络请求的总入口处,解决一些panic和数组越界问题
日志优化,去除遍历结果集时因io.EOF错误记录的日志
## svn 15619
驱动接口方法添加同步锁
驱动日志修改bug,可以记录SQL语句和参数值了
## svn 15357
发布方言包,支持gorm v1和v2框架,方言包位于达梦安装目录的drivers/go目录中,详细使用说明参考《DM8程序员手册》
## svn 15157
修复了字符大字段(Clob)中存在乱码字符时,读取结果会漏读一些字符的问题
修复了开启SSL后并发创建连接导致panic的问题
## svn 15035
修复了连接串属性doSwitch=1时,语句不会自动切换和重连的问题
修复了连接重置后,可能出现的空指针问题
## svn 14992
修复了连接串属性doSwitch=1时,连接不会自动切换和重连的问题
修复了连接串属性loginMode=默认值4时,备库可能会被优先连接的问题
## svn 14589
sql.Result.LastInsertId()函数能优先返回自增列的值,如果没有则返回数据库表内部的rowid
修复了开启事务时指定只读不生效的问题
+61
View File
@@ -0,0 +1,61 @@
# dm
### 介绍
```
go get gitee.com/chunanyong/dm
```
达梦数据库官方Go驱动,本项目和官方驱动版本同步,方便go mod 使用.
安装达梦数据库(版本>=8.1.1.126),安装目录下 drivers/go/dm-go-driver.zip
达梦官方文档:https://eco.dameng.com/docs/zh-cn/app-dev/go-go.html
资源下载:https://eco.dameng.com/download/
达梦官方Go驱动包:https://package.dameng.com/eco/adapter/resource/go/dm-go-driver.zip
达梦官方论坛(提交bug):https://eco.dameng.com/community/question
### zorm
Go轻量ORM https://gitee.com/chunanyong/zorm 原生支持达梦数据库
### DSN
dm://userName:password@127.0.0.1:5236?schema=DBName
用户名(userName)默认就是数据库的名称,达梦用户模式和数据库名称是对应的,也可以通过schema参数指定数据库
建议达梦使用UTF-8字符编码,不区分大小写,建表语句的字段名不要带""双引号
密码中包含特殊字符时,密码使用url.PathEscape进行Escape处理,并在DSN中加入&escapeProcess=true 参见:https://eco.dameng.com/community/question/d152258b30bd0fc030d15e6a4afd5fc2
### bug
- 达梦开启等保参数 COMM_ENCRYPT_NAME = AES128_ECB,导致连接异常
### 版本号
Go三段位版本号和达梦四段位版本号不兼容,统一使用1.达梦主版本号.发布的小版本号,具体查看标签的备注
* v1.8.22 来自 达梦8.1.4.170
* v1.8.21 来自 达梦8.1.4.116
* v1.8.20 来自 达梦8.1.4.80
* v1.8.19 来自 达梦8.1.4.48
* v1.8.18 来自 达梦8.1.4.6
* v1.8.17 来自 达梦8.1.4.6
* v1.8.16 来自 达梦8.1.3.162
* v1.8.15 来自 达梦8.1.3.140
* v1.8.14 来自 达梦8.1.3.100
* v1.8.13 来自 达梦8.1.3.62
* v1.8.12 来自 达梦8.1.3.12
* v1.8.11 来自 达梦8.1.2.192
* v1.8.10 来自 达梦8.1.2.174
* v1.8.9 来自 达梦8.1.2.162
* v1.8.8 来自 达梦8.1.2.138
* v1.8.7 来自 达梦8.1.2.128
* v1.8.6 来自 达梦8.1.2.114
* v1.8.5 来自 达梦8.1.2.94
* v1.8.4 来自 达梦8.1.2.84
* v1.8.3 来自 达梦8.1.2.38
* v1.8.2 来自 达梦8.1.2.18
* v1.8.1 来自 达梦8.1.1.190
* v1.8.0 来自 达梦8.1.1.126
+3
View File
@@ -0,0 +1,3 @@
#8.1.4.170
#2025.11.21
#43114
+863
View File
@@ -0,0 +1,863 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"bytes"
"context"
"crypto/tls"
"fmt"
"net"
"strconv"
"time"
"unicode/utf8"
"gitee.com/chunanyong/dm/security"
)
const (
Dm_build_412 = 8192
Dm_build_413 = 2 * time.Second
)
type dm_build_414 struct {
dm_build_415 net.Conn
dm_build_416 *tls.Conn
dm_build_417 *Dm_build_78
dm_build_418 *DmConnection
dm_build_419 security.Cipher
dm_build_420 bool
dm_build_421 bool
dm_build_422 *security.DhKey
dm_build_423 bool
dm_build_424 string
dm_build_425 bool
}
func dm_build_426(dm_build_427 context.Context, dm_build_428 *DmConnection) (*dm_build_414, error) {
var dm_build_429 net.Conn
var dm_build_430 error
dialsLock.RLock()
dm_build_431, dm_build_432 := dials[dm_build_428.dmConnector.dialName]
dialsLock.RUnlock()
if dm_build_432 {
dm_build_429, dm_build_430 = dm_build_431(dm_build_427, dm_build_428.dmConnector.host+":"+strconv.Itoa(int(dm_build_428.dmConnector.port)))
} else {
dm_build_429, dm_build_430 = dm_build_434(dm_build_428.dmConnector.host+":"+strconv.Itoa(int(dm_build_428.dmConnector.port)), time.Duration(dm_build_428.dmConnector.socketTimeout)*time.Second)
}
if dm_build_430 != nil {
return nil, dm_build_430
}
dm_build_433 := dm_build_414{}
dm_build_433.dm_build_415 = dm_build_429
dm_build_433.dm_build_417 = Dm_build_81(Dm_build_707)
dm_build_433.dm_build_418 = dm_build_428
dm_build_433.dm_build_420 = false
dm_build_433.dm_build_421 = false
dm_build_433.dm_build_423 = false
dm_build_433.dm_build_424 = ""
dm_build_433.dm_build_425 = false
dm_build_428.Access = &dm_build_433
return &dm_build_433, nil
}
func dm_build_434(dm_build_435 string, dm_build_436 time.Duration) (net.Conn, error) {
dm_build_437, dm_build_438 := net.DialTimeout("tcp", dm_build_435, dm_build_436)
if dm_build_438 != nil {
return &net.TCPConn{}, ECGO_COMMUNITION_ERROR.addDetail("\tdial address: " + dm_build_435).throw()
}
if tcpConn, ok := dm_build_437.(*net.TCPConn); ok {
tcpConn.SetKeepAlive(true)
tcpConn.SetKeepAlivePeriod(Dm_build_413)
tcpConn.SetNoDelay(true)
}
return dm_build_437, nil
}
func (dm_build_440 *dm_build_414) dm_build_439(dm_build_441 dm_build_828) bool {
var dm_build_442 = dm_build_440.dm_build_418.dmConnector.compress
if dm_build_441.dm_build_843() == Dm_build_735 || dm_build_442 == Dm_build_784 {
return false
}
if dm_build_442 == Dm_build_782 {
return true
} else if dm_build_442 == Dm_build_783 {
return !dm_build_440.dm_build_418.Local && dm_build_441.dm_build_841() > Dm_build_781
}
return false
}
func (dm_build_444 *dm_build_414) dm_build_443(dm_build_445 dm_build_828) bool {
var dm_build_446 = dm_build_444.dm_build_418.dmConnector.compress
if dm_build_445.dm_build_843() == Dm_build_735 || dm_build_446 == Dm_build_784 {
return false
}
if dm_build_446 == Dm_build_782 {
return true
} else if dm_build_446 == Dm_build_783 {
return dm_build_444.dm_build_417.Dm_build_345(Dm_build_743) == 1
}
return false
}
func (dm_build_448 *dm_build_414) dm_build_447(dm_build_449 dm_build_828) (err error) {
defer func() {
if p := recover(); p != nil {
if _, ok := p.(string); ok {
err = ECGO_COMMUNITION_ERROR.addDetail("\t" + p.(string)).throw()
} else {
err = fmt.Errorf("internal error: %v", p)
}
}
}()
dm_build_451 := dm_build_449.dm_build_841()
if dm_build_451 > 0 {
if dm_build_448.dm_build_439(dm_build_449) {
var retBytes, err = Compress(dm_build_448.dm_build_417, Dm_build_736, int(dm_build_451), int(dm_build_448.dm_build_418.dmConnector.compressID))
if err != nil {
return err
}
dm_build_448.dm_build_417.Dm_build_92(Dm_build_736)
dm_build_448.dm_build_417.Dm_build_133(dm_build_451)
dm_build_448.dm_build_417.Dm_build_161(retBytes)
dm_build_449.dm_build_842(int32(len(retBytes)) + ULINT_SIZE)
dm_build_448.dm_build_417.Dm_build_265(Dm_build_743, 1)
}
if dm_build_448.dm_build_421 {
dm_build_451 = dm_build_449.dm_build_841()
var retBytes = dm_build_448.dm_build_419.Encrypt(dm_build_448.dm_build_417.Dm_build_372(Dm_build_736, int(dm_build_451)), true)
dm_build_448.dm_build_417.Dm_build_92(Dm_build_736)
dm_build_448.dm_build_417.Dm_build_161(retBytes)
dm_build_449.dm_build_842(int32(len(retBytes)))
}
}
if dm_build_448.dm_build_417.Dm_build_90() > Dm_build_708 {
return ECGO_MSG_TOO_LONG.throw()
}
dm_build_449.dm_build_837()
if dm_build_448.dm_build_690(dm_build_449) {
if dm_build_448.dm_build_416 != nil {
dm_build_448.dm_build_417.Dm_build_95(0)
if _, err := dm_build_448.dm_build_417.Dm_build_114(dm_build_448.dm_build_416); err != nil {
return err
}
}
} else {
dm_build_448.dm_build_417.Dm_build_95(0)
if _, err := dm_build_448.dm_build_417.Dm_build_114(dm_build_448.dm_build_415); err != nil {
return err
}
}
return nil
}
func (dm_build_453 *dm_build_414) dm_build_452(dm_build_454 dm_build_828) (err error) {
defer func() {
if p := recover(); p != nil {
if _, ok := p.(string); ok {
err = ECGO_COMMUNITION_ERROR.addDetail("\t" + p.(string)).throw()
} else {
err = fmt.Errorf("internal error: %v", p)
}
}
}()
dm_build_456 := int32(0)
if dm_build_453.dm_build_690(dm_build_454) {
if dm_build_453.dm_build_416 != nil {
dm_build_453.dm_build_417.Dm_build_92(0)
if _, err := dm_build_453.dm_build_417.Dm_build_108(dm_build_453.dm_build_416, Dm_build_736); err != nil {
return err
}
dm_build_456 = dm_build_454.dm_build_841()
if dm_build_456 > 0 {
if _, err := dm_build_453.dm_build_417.Dm_build_108(dm_build_453.dm_build_416, int(dm_build_456)); err != nil {
return err
}
}
}
} else {
dm_build_453.dm_build_417.Dm_build_92(0)
if _, err := dm_build_453.dm_build_417.Dm_build_108(dm_build_453.dm_build_415, Dm_build_736); err != nil {
return err
}
dm_build_456 = dm_build_454.dm_build_841()
if dm_build_456 > 0 {
if _, err := dm_build_453.dm_build_417.Dm_build_108(dm_build_453.dm_build_415, int(dm_build_456)); err != nil {
return err
}
}
}
dm_build_454.dm_build_838()
dm_build_456 = dm_build_454.dm_build_841()
if dm_build_456 <= 0 {
return nil
}
if dm_build_453.dm_build_421 {
ebytes := dm_build_453.dm_build_417.Dm_build_372(Dm_build_736, int(dm_build_456))
bytes, err := dm_build_453.dm_build_419.Decrypt(ebytes, true)
if err != nil {
return err
}
dm_build_453.dm_build_417.Dm_build_92(Dm_build_736)
dm_build_453.dm_build_417.Dm_build_161(bytes)
dm_build_454.dm_build_842(int32(len(bytes)))
}
if dm_build_453.dm_build_443(dm_build_454) {
dm_build_456 = dm_build_454.dm_build_841()
cbytes := dm_build_453.dm_build_417.Dm_build_372(Dm_build_736+ULINT_SIZE, int(dm_build_456-ULINT_SIZE))
bytes, err := UnCompress(cbytes, int(dm_build_453.dm_build_418.dmConnector.compressID))
if err != nil {
return err
}
dm_build_453.dm_build_417.Dm_build_92(Dm_build_736)
dm_build_453.dm_build_417.Dm_build_161(bytes)
dm_build_454.dm_build_842(int32(len(bytes)))
}
return nil
}
func (dm_build_458 *dm_build_414) dm_build_457(dm_build_459 dm_build_828) (dm_build_460 interface{}, dm_build_461 error) {
if dm_build_458.dm_build_425 {
return nil, ECGO_CONNECTION_CLOSED.throw()
}
dm_build_462 := dm_build_458.dm_build_418
dm_build_462.mu.Lock()
defer dm_build_462.mu.Unlock()
dm_build_461 = dm_build_459.dm_build_832(dm_build_459)
if dm_build_461 != nil {
return nil, dm_build_461
}
dm_build_461 = dm_build_458.dm_build_447(dm_build_459)
if dm_build_461 != nil {
return nil, dm_build_461
}
dm_build_461 = dm_build_458.dm_build_452(dm_build_459)
if dm_build_461 != nil {
return nil, dm_build_461
}
return dm_build_459.dm_build_836(dm_build_459)
}
func (dm_build_464 *dm_build_414) dm_build_463() (*dm_build_1287, error) {
Dm_build_465 := dm_build_1293(dm_build_464)
_, dm_build_466 := dm_build_464.dm_build_457(Dm_build_465)
if dm_build_466 != nil {
return nil, dm_build_466
}
return Dm_build_465, nil
}
func (dm_build_468 *dm_build_414) dm_build_467() error {
dm_build_469 := dm_build_1152(dm_build_468)
_, dm_build_470 := dm_build_468.dm_build_457(dm_build_469)
if dm_build_470 != nil {
return dm_build_470
}
return nil
}
func (dm_build_472 *dm_build_414) dm_build_471() error {
var dm_build_473 *dm_build_1287
var err error
if dm_build_473, err = dm_build_472.dm_build_463(); err != nil {
return err
}
if dm_build_472.dm_build_418.sslEncrypt == 2 {
if err = dm_build_472.dm_build_686(false); err != nil {
return ECGO_INIT_SSL_FAILED.addDetail("\n" + err.Error()).throw()
}
} else if dm_build_472.dm_build_418.sslEncrypt == 1 {
if err = dm_build_472.dm_build_686(true); err != nil {
return ECGO_INIT_SSL_FAILED.addDetail("\n" + err.Error()).throw()
}
}
if dm_build_472.dm_build_421 || dm_build_472.dm_build_420 {
k, err := dm_build_472.dm_build_676()
if err != nil {
return err
}
sessionKey := security.ComputeSessionKey(k, dm_build_473.Dm_build_1291)
encryptType := dm_build_473.dm_build_1289
hashType := int(dm_build_473.Dm_build_1290)
if encryptType == -1 {
encryptType = security.DES_CFB
}
if hashType == -1 {
hashType = security.MD5
}
err = dm_build_472.dm_build_679(encryptType, sessionKey, dm_build_472.dm_build_418.dmConnector.cipherPath, hashType)
if err != nil {
return err
}
}
if err := dm_build_472.dm_build_467(); err != nil {
return err
}
return nil
}
func (dm_build_476 *dm_build_414) Dm_build_475(dm_build_477 *DmStatement) error {
dm_build_478 := dm_build_1317(dm_build_476, dm_build_477)
_, dm_build_479 := dm_build_476.dm_build_457(dm_build_478)
if dm_build_479 != nil {
return dm_build_479
}
return nil
}
func (dm_build_481 *dm_build_414) Dm_build_480(dm_build_482 int32) error {
dm_build_483 := dm_build_1327(dm_build_481, dm_build_482)
_, dm_build_484 := dm_build_481.dm_build_457(dm_build_483)
if dm_build_484 != nil {
return dm_build_484
}
return nil
}
func (dm_build_486 *dm_build_414) Dm_build_485(dm_build_487 *DmStatement, dm_build_488 bool, dm_build_489 int16) (*execRetInfo, error) {
dm_build_490 := dm_build_1193(dm_build_486, dm_build_487, dm_build_488, dm_build_489)
dm_build_491, dm_build_492 := dm_build_486.dm_build_457(dm_build_490)
if dm_build_492 != nil {
return nil, dm_build_492
}
return dm_build_491.(*execRetInfo), nil
}
func (dm_build_494 *dm_build_414) Dm_build_493(dm_build_495 *DmStatement, dm_build_496 int16) (*execRetInfo, error) {
return dm_build_494.Dm_build_485(dm_build_495, false, Dm_build_788)
}
func (dm_build_498 *dm_build_414) Dm_build_497(dm_build_499 *DmStatement, dm_build_500 []OptParameter) (*execRetInfo, error) {
dm_build_501, dm_build_502 := dm_build_498.dm_build_457(dm_build_931(dm_build_498, dm_build_499, dm_build_500))
if dm_build_502 != nil {
return nil, dm_build_502
}
return dm_build_501.(*execRetInfo), nil
}
func (dm_build_504 *dm_build_414) Dm_build_503(dm_build_505 *DmStatement, dm_build_506 int16) (*execRetInfo, error) {
return dm_build_504.Dm_build_485(dm_build_505, true, dm_build_506)
}
func (dm_build_508 *dm_build_414) Dm_build_507(dm_build_509 *DmStatement, dm_build_510 [][]interface{}) (*execRetInfo, error) {
dm_build_511 := dm_build_963(dm_build_508, dm_build_509, dm_build_510)
dm_build_512, dm_build_513 := dm_build_508.dm_build_457(dm_build_511)
if dm_build_513 != nil {
return nil, dm_build_513
}
return dm_build_512.(*execRetInfo), nil
}
func (dm_build_515 *dm_build_414) Dm_build_514(dm_build_516 *DmStatement, dm_build_517 [][]interface{}, dm_build_518 bool) (*execRetInfo, error) {
var dm_build_519, dm_build_520 = 0, 0
var dm_build_521 = len(dm_build_517)
var dm_build_522 [][]interface{}
var dm_build_523 = NewExceInfo()
dm_build_523.updateCounts = make([]int64, dm_build_521)
var dm_build_524 = false
for dm_build_519 < dm_build_521 {
for dm_build_520 = dm_build_519; dm_build_520 < dm_build_521; dm_build_520++ {
paramData := dm_build_517[dm_build_520]
bindData := make([]interface{}, dm_build_516.paramCount)
dm_build_524 = false
for icol := 0; icol < int(dm_build_516.paramCount); icol++ {
if dm_build_516.bindParams[icol].ioType == IO_TYPE_OUT {
continue
}
if dm_build_515.dm_build_659(bindData, paramData, icol) {
dm_build_524 = true
break
}
}
if dm_build_524 {
break
}
dm_build_522 = append(dm_build_522, bindData)
}
if dm_build_520 != dm_build_519 {
tmpExecInfo, err := dm_build_515.Dm_build_507(dm_build_516, dm_build_522)
if err != nil {
return nil, err
}
dm_build_522 = dm_build_522[0:0]
dm_build_523.union(tmpExecInfo, dm_build_519, dm_build_520-dm_build_519)
}
if dm_build_520 < dm_build_521 {
tmpExecInfo, err := dm_build_515.Dm_build_533(dm_build_516, dm_build_517[dm_build_520], dm_build_518)
if err != nil {
return nil, err
}
dm_build_518 = true
dm_build_523.union(tmpExecInfo, dm_build_520, 1)
}
dm_build_519 = dm_build_520 + 1
}
for _, i := range dm_build_523.updateCounts {
if i > 0 {
dm_build_523.updateCount += i
}
}
return dm_build_523, nil
}
func (dm_build_526 *dm_build_414) dm_build_525(dm_build_527 *DmStatement, dm_build_528 []parameter) error {
if !dm_build_527.prepared {
retInfo, err := dm_build_526.Dm_build_485(dm_build_527, false, Dm_build_788)
if err != nil {
return nil
}
dm_build_527.serverParams = retInfo.serverParams
dm_build_527.paramCount = int32(len(dm_build_527.serverParams))
dm_build_527.prepared = true
}
dm_build_529 := dm_build_1182(dm_build_526, dm_build_527, dm_build_527.bindParams)
dm_build_530, err := dm_build_526.dm_build_457(dm_build_529)
if err != nil {
return nil
}
retInfo := dm_build_530.(*execRetInfo)
if retInfo.serverParams != nil && len(retInfo.serverParams) > 0 {
dm_build_527.serverParams = retInfo.serverParams
dm_build_527.paramCount = int32(len(dm_build_527.serverParams))
}
dm_build_527.preExec = true
return nil
}
func (dm_build_534 *dm_build_414) Dm_build_533(dm_build_535 *DmStatement, dm_build_536 []interface{}, dm_build_537 bool) (*execRetInfo, error) {
var dm_build_538 = make([]interface{}, dm_build_535.paramCount)
for icol := 0; icol < int(dm_build_535.paramCount); icol++ {
if dm_build_535.bindParams[icol].ioType == IO_TYPE_OUT {
continue
}
if dm_build_534.dm_build_659(dm_build_538, dm_build_536, icol) {
if !dm_build_537 {
dm_build_534.dm_build_525(dm_build_535, dm_build_535.bindParams)
dm_build_537 = true
}
dm_build_534.dm_build_665(dm_build_535, dm_build_535.bindParams[icol], icol, dm_build_536[icol].(iOffRowBinder))
dm_build_538[icol] = ParamDataEnum_OFF_ROW
}
}
var dm_build_539 = make([][]interface{}, 1, 1)
dm_build_539[0] = dm_build_538
dm_build_540 := dm_build_963(dm_build_534, dm_build_535, dm_build_539)
dm_build_541, dm_build_542 := dm_build_534.dm_build_457(dm_build_540)
if dm_build_542 != nil {
return nil, dm_build_542
}
return dm_build_541.(*execRetInfo), nil
}
func (dm_build_544 *dm_build_414) Dm_build_543(dm_build_545 *DmStatement, dm_build_546 int16) (*execRetInfo, error) {
dm_build_547 := dm_build_1169(dm_build_544, dm_build_545, dm_build_546)
dm_build_548, dm_build_549 := dm_build_544.dm_build_457(dm_build_547)
if dm_build_549 != nil {
return nil, dm_build_549
}
return dm_build_548.(*execRetInfo), nil
}
func (dm_build_551 *dm_build_414) Dm_build_550(dm_build_552 *innerRows, dm_build_553 int64) (*execRetInfo, error) {
dm_build_554 := dm_build_1070(dm_build_551, dm_build_552, dm_build_553, INT64_MAX)
dm_build_555, dm_build_556 := dm_build_551.dm_build_457(dm_build_554)
if dm_build_556 != nil {
return nil, dm_build_556
}
return dm_build_555.(*execRetInfo), nil
}
func (dm_build_558 *dm_build_414) Commit() error {
dm_build_559 := dm_build_916(dm_build_558)
_, dm_build_560 := dm_build_558.dm_build_457(dm_build_559)
if dm_build_560 != nil {
return dm_build_560
}
return nil
}
func (dm_build_562 *dm_build_414) Rollback() error {
dm_build_563 := dm_build_1231(dm_build_562)
_, dm_build_564 := dm_build_562.dm_build_457(dm_build_563)
if dm_build_564 != nil {
return dm_build_564
}
return nil
}
func (dm_build_566 *dm_build_414) Dm_build_565(dm_build_567 *DmConnection) error {
dm_build_568 := dm_build_1236(dm_build_566, dm_build_567.IsoLevel)
_, dm_build_569 := dm_build_566.dm_build_457(dm_build_568)
if dm_build_569 != nil {
return dm_build_569
}
return nil
}
func (dm_build_571 *dm_build_414) Dm_build_570(dm_build_572 *DmStatement, dm_build_573 string) error {
dm_build_574 := dm_build_921(dm_build_571, dm_build_572, dm_build_573)
_, dm_build_575 := dm_build_571.dm_build_457(dm_build_574)
if dm_build_575 != nil {
return dm_build_575
}
return nil
}
func (dm_build_577 *dm_build_414) Dm_build_576(dm_build_578 []uint32) ([]int64, error) {
dm_build_579 := dm_build_1335(dm_build_577, dm_build_578)
dm_build_580, dm_build_581 := dm_build_577.dm_build_457(dm_build_579)
if dm_build_581 != nil {
return nil, dm_build_581
}
return dm_build_580.([]int64), nil
}
func (dm_build_583 *dm_build_414) Close() error {
if dm_build_583.dm_build_425 {
return nil
}
dm_build_584 := dm_build_583.dm_build_415.Close()
if dm_build_584 != nil {
return dm_build_584
}
dm_build_583.dm_build_418 = nil
dm_build_583.dm_build_425 = true
return nil
}
func (dm_build_586 *dm_build_414) dm_build_585(dm_build_587 *lob) (int64, error) {
dm_build_588 := dm_build_1103(dm_build_586, dm_build_587)
dm_build_589, dm_build_590 := dm_build_586.dm_build_457(dm_build_588)
if dm_build_590 != nil {
return 0, dm_build_590
}
return dm_build_589.(int64), nil
}
func (dm_build_592 *dm_build_414) dm_build_591(dm_build_593 *lob, dm_build_594 int32, dm_build_595 int32) (*lobRetInfo, error) {
dm_build_596 := dm_build_1088(dm_build_592, dm_build_593, int(dm_build_594), int(dm_build_595))
dm_build_597, dm_build_598 := dm_build_592.dm_build_457(dm_build_596)
if dm_build_598 != nil {
return nil, dm_build_598
}
return dm_build_597.(*lobRetInfo), nil
}
func (dm_build_600 *dm_build_414) dm_build_599(dm_build_601 *DmBlob, dm_build_602 int32, dm_build_603 int32) ([]byte, error) {
var dm_build_604 = make([]byte, dm_build_603)
var dm_build_605 int32 = 0
var dm_build_606 int32 = 0
var dm_build_607 *lobRetInfo
var dm_build_608 []byte
var dm_build_609 error
for dm_build_605 < dm_build_603 {
dm_build_606 = dm_build_603 - dm_build_605
if dm_build_606 > Dm_build_821 {
dm_build_606 = Dm_build_821
}
dm_build_607, dm_build_609 = dm_build_600.dm_build_591(&dm_build_601.lob, dm_build_602+dm_build_605, dm_build_606)
if dm_build_609 != nil {
return nil, dm_build_609
}
dm_build_608 = dm_build_607.data
if dm_build_608 == nil || len(dm_build_608) == 0 {
break
}
Dm_build_1346.Dm_build_1402(dm_build_604, int(dm_build_605), dm_build_608, 0, len(dm_build_608))
dm_build_605 += int32(len(dm_build_608))
if dm_build_601.readOver {
break
}
}
return dm_build_604, nil
}
func (dm_build_611 *dm_build_414) dm_build_610(dm_build_612 *DmClob, dm_build_613 int32, dm_build_614 int32) (string, error) {
var dm_build_615 bytes.Buffer
var dm_build_616 int32 = 0
var dm_build_617 int32 = 0
var dm_build_618 *lobRetInfo
var dm_build_619 []byte
var dm_build_620 string
var dm_build_621 error
for dm_build_616 < dm_build_614 {
dm_build_617 = dm_build_614 - dm_build_616
if dm_build_617 > Dm_build_821/2 {
dm_build_617 = Dm_build_821 / 2
}
dm_build_618, dm_build_621 = dm_build_611.dm_build_591(&dm_build_612.lob, dm_build_613+dm_build_616, dm_build_617)
if dm_build_621 != nil {
return "", dm_build_621
}
dm_build_619 = dm_build_618.data
if dm_build_619 == nil || len(dm_build_619) == 0 {
break
}
dm_build_620 = Dm_build_1346.Dm_build_1503(dm_build_619, 0, len(dm_build_619), dm_build_612.serverEncoding, dm_build_611.dm_build_418)
dm_build_615.WriteString(dm_build_620)
var strLen = dm_build_618.charLen
if strLen == -1 {
strLen = int64(utf8.RuneCountInString(dm_build_620))
}
dm_build_616 += int32(strLen)
if dm_build_612.readOver {
break
}
}
return dm_build_615.String(), nil
}
func (dm_build_623 *dm_build_414) dm_build_622(dm_build_624 *DmClob, dm_build_625 int, dm_build_626 string, dm_build_627 string) (int, error) {
var dm_build_628 = Dm_build_1346.Dm_build_1562(dm_build_626, dm_build_627, dm_build_623.dm_build_418)
var dm_build_629 = 0
var dm_build_630 = len(dm_build_628)
var dm_build_631 = 0
var dm_build_632 = 0
var dm_build_633 = 0
var dm_build_634 = dm_build_630/Dm_build_820 + 1
var dm_build_635 byte = 0
var dm_build_636 byte = 0x01
var dm_build_637 byte = 0x02
for i := 0; i < dm_build_634; i++ {
dm_build_635 = 0
if i == 0 {
dm_build_635 |= dm_build_636
}
if i == dm_build_634-1 {
dm_build_635 |= dm_build_637
}
dm_build_633 = dm_build_630 - dm_build_632
if dm_build_633 > Dm_build_820 {
dm_build_633 = Dm_build_820
}
setLobData := dm_build_1250(dm_build_623, &dm_build_624.lob, dm_build_635, dm_build_625, dm_build_628, dm_build_629, dm_build_633)
ret, err := dm_build_623.dm_build_457(setLobData)
if err != nil {
return 0, err
}
tmp := ret.(int32)
if err != nil {
return -1, err
}
if tmp <= 0 {
return dm_build_631, nil
} else {
dm_build_625 += int(tmp)
dm_build_631 += int(tmp)
dm_build_632 += dm_build_633
dm_build_629 += dm_build_633
}
}
return dm_build_631, nil
}
func (dm_build_639 *dm_build_414) dm_build_638(dm_build_640 *DmBlob, dm_build_641 int, dm_build_642 []byte) (int, error) {
var dm_build_643 = 0
var dm_build_644 = len(dm_build_642)
var dm_build_645 = 0
var dm_build_646 = 0
var dm_build_647 = 0
var dm_build_648 = dm_build_644/Dm_build_820 + 1
var dm_build_649 byte = 0
var dm_build_650 byte = 0x01
var dm_build_651 byte = 0x02
for i := 0; i < dm_build_648; i++ {
dm_build_649 = 0
if i == 0 {
dm_build_649 |= dm_build_650
}
if i == dm_build_648-1 {
dm_build_649 |= dm_build_651
}
dm_build_647 = dm_build_644 - dm_build_646
if dm_build_647 > Dm_build_820 {
dm_build_647 = Dm_build_820
}
setLobData := dm_build_1250(dm_build_639, &dm_build_640.lob, dm_build_649, dm_build_641, dm_build_642, dm_build_643, dm_build_647)
ret, err := dm_build_639.dm_build_457(setLobData)
if err != nil {
return 0, err
}
tmp := ret.(int32)
if tmp <= 0 {
return dm_build_645, nil
} else {
dm_build_641 += int(tmp)
dm_build_645 += int(tmp)
dm_build_646 += dm_build_647
dm_build_643 += dm_build_647
}
}
return dm_build_645, nil
}
func (dm_build_653 *dm_build_414) dm_build_652(dm_build_654 *lob, dm_build_655 int) (int64, error) {
dm_build_656 := dm_build_1114(dm_build_653, dm_build_654, dm_build_655)
dm_build_657, dm_build_658 := dm_build_653.dm_build_457(dm_build_656)
if dm_build_658 != nil {
return dm_build_654.length, dm_build_658
}
return dm_build_657.(int64), nil
}
func (dm_build_660 *dm_build_414) dm_build_659(dm_build_661 []interface{}, dm_build_662 []interface{}, dm_build_663 int) bool {
var dm_build_664 = false
dm_build_661[dm_build_663] = dm_build_662[dm_build_663]
if binder, ok := dm_build_662[dm_build_663].(iOffRowBinder); ok {
dm_build_664 = true
dm_build_661[dm_build_663] = make([]byte, 0)
var lob lob
if l, ok := binder.getObj().(DmBlob); ok {
lob = l.lob
} else if l, ok := binder.getObj().(DmClob); ok {
lob = l.lob
}
if &lob != nil && lob.canOptimized(dm_build_660.dm_build_418) {
dm_build_661[dm_build_663] = &lobCtl{lob.buildCtlData()}
dm_build_664 = false
}
} else {
dm_build_661[dm_build_663] = dm_build_662[dm_build_663]
}
return dm_build_664
}
func (dm_build_666 *dm_build_414) dm_build_665(dm_build_667 *DmStatement, dm_build_668 parameter, dm_build_669 int, dm_build_670 iOffRowBinder) error {
var dm_build_671 = Dm_build_4()
dm_build_670.read(dm_build_671)
var dm_build_672 = 0
for !dm_build_670.isReadOver() || dm_build_671.Dm_build_5() > 0 {
if !dm_build_670.isReadOver() && dm_build_671.Dm_build_5() < Dm_build_820 {
dm_build_670.read(dm_build_671)
}
if dm_build_671.Dm_build_5() > Dm_build_820 {
dm_build_672 = Dm_build_820
} else {
dm_build_672 = dm_build_671.Dm_build_5()
}
putData := dm_build_1221(dm_build_666, dm_build_667, int16(dm_build_669), dm_build_671, int32(dm_build_672))
_, err := dm_build_666.dm_build_457(putData)
if err != nil {
return err
}
}
return nil
}
func (dm_build_674 *dm_build_414) dm_build_673() ([]byte, error) {
var dm_build_675 error
if dm_build_674.dm_build_422 == nil {
if dm_build_674.dm_build_422, dm_build_675 = security.NewClientKeyPair(); dm_build_675 != nil {
return nil, dm_build_675
}
}
return security.Bn2Bytes(dm_build_674.dm_build_422.GetY(), security.DH_KEY_LENGTH), nil
}
func (dm_build_677 *dm_build_414) dm_build_676() (*security.DhKey, error) {
var dm_build_678 error
if dm_build_677.dm_build_422 == nil {
if dm_build_677.dm_build_422, dm_build_678 = security.NewClientKeyPair(); dm_build_678 != nil {
return nil, dm_build_678
}
}
return dm_build_677.dm_build_422, nil
}
func (dm_build_680 *dm_build_414) dm_build_679(dm_build_681 int, dm_build_682 []byte, dm_build_683 string, dm_build_684 int) (dm_build_685 error) {
if dm_build_681 > 0 && dm_build_681 < security.MIN_EXTERNAL_CIPHER_ID && dm_build_682 != nil {
dm_build_680.dm_build_419, dm_build_685 = security.NewSymmCipher(dm_build_681, dm_build_682)
} else if dm_build_681 >= security.MIN_EXTERNAL_CIPHER_ID {
if dm_build_680.dm_build_419, dm_build_685 = security.NewThirdPartCipher(dm_build_681, dm_build_682, dm_build_683, dm_build_684); dm_build_685 != nil {
dm_build_685 = THIRD_PART_CIPHER_INIT_FAILED.addDetailln(dm_build_685.Error()).throw()
}
}
return
}
func (dm_build_687 *dm_build_414) dm_build_686(dm_build_688 bool) (dm_build_689 error) {
if dm_build_687.dm_build_416, dm_build_689 = security.NewTLSFromTCP(dm_build_687.dm_build_415, dm_build_687.dm_build_418.dmConnector.sslCertPath, dm_build_687.dm_build_418.dmConnector.sslKeyPath, dm_build_687.dm_build_418.dmConnector.user); dm_build_689 != nil {
return
}
if !dm_build_688 {
dm_build_687.dm_build_416 = nil
}
return
}
func (dm_build_691 *dm_build_414) dm_build_690(dm_build_692 dm_build_828) bool {
return dm_build_692.dm_build_843() != Dm_build_735 && dm_build_691.dm_build_418.sslEncrypt == 1
}
+45
View File
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
type ArrayDescriptor struct {
m_typeDesc *TypeDescriptor
}
func newArrayDescriptor(fulName string, conn *DmConnection) (*ArrayDescriptor, error) {
ad := new(ArrayDescriptor)
if fulName == "" {
return nil, ECGO_INVALID_COMPLEX_TYPE_NAME.throw()
}
ad.m_typeDesc = newTypeDescriptorWithFulName(fulName, conn)
err := ad.m_typeDesc.parseDescByName()
if err != nil {
return nil, err
}
return ad, nil
}
func newArrayDescriptorByTypeDescriptor(desc *TypeDescriptor) *ArrayDescriptor {
ad := new(ArrayDescriptor)
ad.m_typeDesc = desc
return ad
}
func (ad *ArrayDescriptor) getMDesc() *TypeDescriptor {
return ad.m_typeDesc
}
func (ad *ArrayDescriptor) getItemDesc() *TypeDescriptor {
return ad.m_typeDesc.m_arrObj
}
func (ad *ArrayDescriptor) getLength() int {
return ad.m_typeDesc.m_length
}
+495
View File
@@ -0,0 +1,495 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"io"
"math"
)
type Dm_build_78 struct {
dm_build_79 []byte
dm_build_80 int
}
func Dm_build_81(dm_build_82 int) *Dm_build_78 {
return &Dm_build_78{make([]byte, 0, dm_build_82), 0}
}
func Dm_build_83(dm_build_84 []byte) *Dm_build_78 {
return &Dm_build_78{dm_build_84, 0}
}
func (dm_build_86 *Dm_build_78) dm_build_85(dm_build_87 int) *Dm_build_78 {
dm_build_88 := len(dm_build_86.dm_build_79)
dm_build_89 := cap(dm_build_86.dm_build_79)
if dm_build_88+dm_build_87 <= dm_build_89 {
dm_build_86.dm_build_79 = dm_build_86.dm_build_79[:dm_build_88+dm_build_87]
} else {
var calCap = int64(math.Max(float64(2*dm_build_89), float64(dm_build_87+dm_build_88)))
nbuf := make([]byte, dm_build_87+dm_build_88, calCap)
copy(nbuf, dm_build_86.dm_build_79)
dm_build_86.dm_build_79 = nbuf
}
return dm_build_86
}
func (dm_build_91 *Dm_build_78) Dm_build_90() int {
return len(dm_build_91.dm_build_79)
}
func (dm_build_93 *Dm_build_78) Dm_build_92(dm_build_94 int) *Dm_build_78 {
for i := dm_build_94; i < len(dm_build_93.dm_build_79); i++ {
dm_build_93.dm_build_79[i] = 0
}
dm_build_93.dm_build_79 = dm_build_93.dm_build_79[:dm_build_94]
return dm_build_93
}
func (dm_build_96 *Dm_build_78) Dm_build_95(dm_build_97 int) *Dm_build_78 {
dm_build_96.dm_build_80 = dm_build_97
return dm_build_96
}
func (dm_build_99 *Dm_build_78) Dm_build_98() int {
return dm_build_99.dm_build_80
}
func (dm_build_101 *Dm_build_78) Dm_build_100(dm_build_102 bool) int {
return len(dm_build_101.dm_build_79) - dm_build_101.dm_build_80
}
func (dm_build_104 *Dm_build_78) Dm_build_103(dm_build_105 int, dm_build_106 bool, dm_build_107 bool) *Dm_build_78 {
if dm_build_106 {
if dm_build_107 {
dm_build_104.dm_build_85(dm_build_105)
} else {
dm_build_104.dm_build_79 = dm_build_104.dm_build_79[:len(dm_build_104.dm_build_79)-dm_build_105]
}
} else {
if dm_build_107 {
dm_build_104.dm_build_80 += dm_build_105
} else {
dm_build_104.dm_build_80 -= dm_build_105
}
}
return dm_build_104
}
func (dm_build_109 *Dm_build_78) Dm_build_108(dm_build_110 io.Reader, dm_build_111 int) (int, error) {
dm_build_112 := len(dm_build_109.dm_build_79)
dm_build_109.dm_build_85(dm_build_111)
dm_build_113 := 0
for dm_build_111 > 0 {
n, err := dm_build_110.Read(dm_build_109.dm_build_79[dm_build_112+dm_build_113:])
if n > 0 && err == io.EOF {
dm_build_113 += n
dm_build_109.dm_build_79 = dm_build_109.dm_build_79[:dm_build_112+dm_build_113]
return dm_build_113, nil
} else if n > 0 && err == nil {
dm_build_111 -= n
dm_build_113 += n
} else if n == 0 && err != nil {
return -1, ECGO_COMMUNITION_ERROR.addDetailln(err.Error()).throw()
}
}
return dm_build_113, nil
}
func (dm_build_115 *Dm_build_78) Dm_build_114(dm_build_116 io.Writer) (*Dm_build_78, error) {
if _, err := dm_build_116.Write(dm_build_115.dm_build_79); err != nil {
return nil, ECGO_COMMUNITION_ERROR.addDetailln(err.Error()).throw()
}
return dm_build_115, nil
}
func (dm_build_118 *Dm_build_78) Dm_build_117(dm_build_119 bool) int {
dm_build_120 := len(dm_build_118.dm_build_79)
dm_build_118.dm_build_85(1)
if dm_build_119 {
return copy(dm_build_118.dm_build_79[dm_build_120:], []byte{1})
} else {
return copy(dm_build_118.dm_build_79[dm_build_120:], []byte{0})
}
}
func (dm_build_122 *Dm_build_78) Dm_build_121(dm_build_123 byte) int {
dm_build_124 := len(dm_build_122.dm_build_79)
dm_build_122.dm_build_85(1)
return copy(dm_build_122.dm_build_79[dm_build_124:], Dm_build_1346.Dm_build_1524(dm_build_123))
}
func (dm_build_126 *Dm_build_78) Dm_build_125(dm_build_127 int8) int {
dm_build_128 := len(dm_build_126.dm_build_79)
dm_build_126.dm_build_85(1)
return copy(dm_build_126.dm_build_79[dm_build_128:], Dm_build_1346.Dm_build_1527(dm_build_127))
}
func (dm_build_130 *Dm_build_78) Dm_build_129(dm_build_131 int16) int {
dm_build_132 := len(dm_build_130.dm_build_79)
dm_build_130.dm_build_85(2)
return copy(dm_build_130.dm_build_79[dm_build_132:], Dm_build_1346.Dm_build_1530(dm_build_131))
}
func (dm_build_134 *Dm_build_78) Dm_build_133(dm_build_135 int32) int {
dm_build_136 := len(dm_build_134.dm_build_79)
dm_build_134.dm_build_85(4)
return copy(dm_build_134.dm_build_79[dm_build_136:], Dm_build_1346.Dm_build_1533(dm_build_135))
}
func (dm_build_138 *Dm_build_78) Dm_build_137(dm_build_139 uint8) int {
dm_build_140 := len(dm_build_138.dm_build_79)
dm_build_138.dm_build_85(1)
return copy(dm_build_138.dm_build_79[dm_build_140:], Dm_build_1346.Dm_build_1545(dm_build_139))
}
func (dm_build_142 *Dm_build_78) Dm_build_141(dm_build_143 uint16) int {
dm_build_144 := len(dm_build_142.dm_build_79)
dm_build_142.dm_build_85(2)
return copy(dm_build_142.dm_build_79[dm_build_144:], Dm_build_1346.Dm_build_1548(dm_build_143))
}
func (dm_build_146 *Dm_build_78) Dm_build_145(dm_build_147 uint32) int {
dm_build_148 := len(dm_build_146.dm_build_79)
dm_build_146.dm_build_85(4)
return copy(dm_build_146.dm_build_79[dm_build_148:], Dm_build_1346.Dm_build_1551(dm_build_147))
}
func (dm_build_150 *Dm_build_78) Dm_build_149(dm_build_151 uint64) int {
dm_build_152 := len(dm_build_150.dm_build_79)
dm_build_150.dm_build_85(8)
return copy(dm_build_150.dm_build_79[dm_build_152:], Dm_build_1346.Dm_build_1554(dm_build_151))
}
func (dm_build_154 *Dm_build_78) Dm_build_153(dm_build_155 float32) int {
dm_build_156 := len(dm_build_154.dm_build_79)
dm_build_154.dm_build_85(4)
return copy(dm_build_154.dm_build_79[dm_build_156:], Dm_build_1346.Dm_build_1551(math.Float32bits(dm_build_155)))
}
func (dm_build_158 *Dm_build_78) Dm_build_157(dm_build_159 float64) int {
dm_build_160 := len(dm_build_158.dm_build_79)
dm_build_158.dm_build_85(8)
return copy(dm_build_158.dm_build_79[dm_build_160:], Dm_build_1346.Dm_build_1554(math.Float64bits(dm_build_159)))
}
func (dm_build_162 *Dm_build_78) Dm_build_161(dm_build_163 []byte) int {
dm_build_164 := len(dm_build_162.dm_build_79)
dm_build_162.dm_build_85(len(dm_build_163))
return copy(dm_build_162.dm_build_79[dm_build_164:], dm_build_163)
}
func (dm_build_166 *Dm_build_78) Dm_build_165(dm_build_167 []byte) int {
return dm_build_166.Dm_build_133(int32(len(dm_build_167))) + dm_build_166.Dm_build_161(dm_build_167)
}
func (dm_build_169 *Dm_build_78) Dm_build_168(dm_build_170 []byte) int {
return dm_build_169.Dm_build_137(uint8(len(dm_build_170))) + dm_build_169.Dm_build_161(dm_build_170)
}
func (dm_build_172 *Dm_build_78) Dm_build_171(dm_build_173 []byte) int {
return dm_build_172.Dm_build_141(uint16(len(dm_build_173))) + dm_build_172.Dm_build_161(dm_build_173)
}
func (dm_build_175 *Dm_build_78) Dm_build_174(dm_build_176 []byte) int {
return dm_build_175.Dm_build_161(dm_build_176) + dm_build_175.Dm_build_121(0)
}
func (dm_build_178 *Dm_build_78) Dm_build_177(dm_build_179 string, dm_build_180 string, dm_build_181 *DmConnection) int {
dm_build_182 := Dm_build_1346.Dm_build_1562(dm_build_179, dm_build_180, dm_build_181)
return dm_build_178.Dm_build_165(dm_build_182)
}
func (dm_build_184 *Dm_build_78) Dm_build_183(dm_build_185 string, dm_build_186 string, dm_build_187 *DmConnection) int {
dm_build_188 := Dm_build_1346.Dm_build_1562(dm_build_185, dm_build_186, dm_build_187)
return dm_build_184.Dm_build_168(dm_build_188)
}
func (dm_build_190 *Dm_build_78) Dm_build_189(dm_build_191 string, dm_build_192 string, dm_build_193 *DmConnection) int {
dm_build_194 := Dm_build_1346.Dm_build_1562(dm_build_191, dm_build_192, dm_build_193)
return dm_build_190.Dm_build_171(dm_build_194)
}
func (dm_build_196 *Dm_build_78) Dm_build_195(dm_build_197 string, dm_build_198 string, dm_build_199 *DmConnection) int {
dm_build_200 := Dm_build_1346.Dm_build_1562(dm_build_197, dm_build_198, dm_build_199)
return dm_build_196.Dm_build_174(dm_build_200)
}
func (dm_build_202 *Dm_build_78) Dm_build_201() byte {
dm_build_203 := Dm_build_1346.Dm_build_1439(dm_build_202.dm_build_79, dm_build_202.dm_build_80)
dm_build_202.dm_build_80++
return dm_build_203
}
func (dm_build_205 *Dm_build_78) Dm_build_204() int16 {
dm_build_206 := Dm_build_1346.Dm_build_1443(dm_build_205.dm_build_79, dm_build_205.dm_build_80)
dm_build_205.dm_build_80 += 2
return dm_build_206
}
func (dm_build_208 *Dm_build_78) Dm_build_207() int32 {
dm_build_209 := Dm_build_1346.Dm_build_1448(dm_build_208.dm_build_79, dm_build_208.dm_build_80)
dm_build_208.dm_build_80 += 4
return dm_build_209
}
func (dm_build_211 *Dm_build_78) Dm_build_210() int64 {
dm_build_212 := Dm_build_1346.Dm_build_1453(dm_build_211.dm_build_79, dm_build_211.dm_build_80)
dm_build_211.dm_build_80 += 8
return dm_build_212
}
func (dm_build_214 *Dm_build_78) Dm_build_213() float32 {
dm_build_215 := Dm_build_1346.Dm_build_1458(dm_build_214.dm_build_79, dm_build_214.dm_build_80)
dm_build_214.dm_build_80 += 4
return dm_build_215
}
func (dm_build_217 *Dm_build_78) Dm_build_216() float64 {
dm_build_218 := Dm_build_1346.Dm_build_1462(dm_build_217.dm_build_79, dm_build_217.dm_build_80)
dm_build_217.dm_build_80 += 8
return dm_build_218
}
func (dm_build_220 *Dm_build_78) Dm_build_219() uint8 {
dm_build_221 := Dm_build_1346.Dm_build_1466(dm_build_220.dm_build_79, dm_build_220.dm_build_80)
dm_build_220.dm_build_80 += 1
return dm_build_221
}
func (dm_build_223 *Dm_build_78) Dm_build_222() uint16 {
dm_build_224 := Dm_build_1346.Dm_build_1470(dm_build_223.dm_build_79, dm_build_223.dm_build_80)
dm_build_223.dm_build_80 += 2
return dm_build_224
}
func (dm_build_226 *Dm_build_78) Dm_build_225() uint32 {
dm_build_227 := Dm_build_1346.Dm_build_1475(dm_build_226.dm_build_79, dm_build_226.dm_build_80)
dm_build_226.dm_build_80 += 4
return dm_build_227
}
func (dm_build_229 *Dm_build_78) Dm_build_228(dm_build_230 int) []byte {
dm_build_231 := Dm_build_1346.Dm_build_1497(dm_build_229.dm_build_79, dm_build_229.dm_build_80, dm_build_230)
dm_build_229.dm_build_80 += dm_build_230
return dm_build_231
}
func (dm_build_233 *Dm_build_78) Dm_build_232() []byte {
return dm_build_233.Dm_build_228(int(dm_build_233.Dm_build_207()))
}
func (dm_build_235 *Dm_build_78) Dm_build_234() []byte {
return dm_build_235.Dm_build_228(int(dm_build_235.Dm_build_201()))
}
func (dm_build_237 *Dm_build_78) Dm_build_236() []byte {
return dm_build_237.Dm_build_228(int(dm_build_237.Dm_build_204()))
}
func (dm_build_239 *Dm_build_78) Dm_build_238(dm_build_240 int) []byte {
return dm_build_239.Dm_build_228(dm_build_240)
}
func (dm_build_242 *Dm_build_78) Dm_build_241() []byte {
dm_build_243 := 0
for dm_build_242.Dm_build_201() != 0 {
dm_build_243++
}
dm_build_242.Dm_build_103(dm_build_243, false, false)
return dm_build_242.Dm_build_228(dm_build_243)
}
func (dm_build_245 *Dm_build_78) Dm_build_244(dm_build_246 int, dm_build_247 string, dm_build_248 *DmConnection) string {
return Dm_build_1346.Dm_build_1598(dm_build_245.Dm_build_228(dm_build_246), dm_build_247, dm_build_248)
}
func (dm_build_250 *Dm_build_78) Dm_build_249(dm_build_251 string, dm_build_252 *DmConnection) string {
return Dm_build_1346.Dm_build_1598(dm_build_250.Dm_build_232(), dm_build_251, dm_build_252)
}
func (dm_build_254 *Dm_build_78) Dm_build_253(dm_build_255 string, dm_build_256 *DmConnection) string {
return Dm_build_1346.Dm_build_1598(dm_build_254.Dm_build_234(), dm_build_255, dm_build_256)
}
func (dm_build_258 *Dm_build_78) Dm_build_257(dm_build_259 string, dm_build_260 *DmConnection) string {
return Dm_build_1346.Dm_build_1598(dm_build_258.Dm_build_236(), dm_build_259, dm_build_260)
}
func (dm_build_262 *Dm_build_78) Dm_build_261(dm_build_263 string, dm_build_264 *DmConnection) string {
return Dm_build_1346.Dm_build_1598(dm_build_262.Dm_build_241(), dm_build_263, dm_build_264)
}
func (dm_build_266 *Dm_build_78) Dm_build_265(dm_build_267 int, dm_build_268 byte) int {
return dm_build_266.Dm_build_301(dm_build_267, Dm_build_1346.Dm_build_1524(dm_build_268))
}
func (dm_build_270 *Dm_build_78) Dm_build_269(dm_build_271 int, dm_build_272 int16) int {
return dm_build_270.Dm_build_301(dm_build_271, Dm_build_1346.Dm_build_1530(dm_build_272))
}
func (dm_build_274 *Dm_build_78) Dm_build_273(dm_build_275 int, dm_build_276 int32) int {
return dm_build_274.Dm_build_301(dm_build_275, Dm_build_1346.Dm_build_1533(dm_build_276))
}
func (dm_build_278 *Dm_build_78) Dm_build_277(dm_build_279 int, dm_build_280 int64) int {
return dm_build_278.Dm_build_301(dm_build_279, Dm_build_1346.Dm_build_1536(dm_build_280))
}
func (dm_build_282 *Dm_build_78) Dm_build_281(dm_build_283 int, dm_build_284 float32) int {
return dm_build_282.Dm_build_301(dm_build_283, Dm_build_1346.Dm_build_1539(dm_build_284))
}
func (dm_build_286 *Dm_build_78) Dm_build_285(dm_build_287 int, dm_build_288 float64) int {
return dm_build_286.Dm_build_301(dm_build_287, Dm_build_1346.Dm_build_1542(dm_build_288))
}
func (dm_build_290 *Dm_build_78) Dm_build_289(dm_build_291 int, dm_build_292 uint8) int {
return dm_build_290.Dm_build_301(dm_build_291, Dm_build_1346.Dm_build_1545(dm_build_292))
}
func (dm_build_294 *Dm_build_78) Dm_build_293(dm_build_295 int, dm_build_296 uint16) int {
return dm_build_294.Dm_build_301(dm_build_295, Dm_build_1346.Dm_build_1548(dm_build_296))
}
func (dm_build_298 *Dm_build_78) Dm_build_297(dm_build_299 int, dm_build_300 uint32) int {
return dm_build_298.Dm_build_301(dm_build_299, Dm_build_1346.Dm_build_1551(dm_build_300))
}
func (dm_build_302 *Dm_build_78) Dm_build_301(dm_build_303 int, dm_build_304 []byte) int {
return copy(dm_build_302.dm_build_79[dm_build_303:], dm_build_304)
}
func (dm_build_306 *Dm_build_78) Dm_build_305(dm_build_307 int, dm_build_308 []byte) int {
return dm_build_306.Dm_build_273(dm_build_307, int32(len(dm_build_308))) + dm_build_306.Dm_build_301(dm_build_307+4, dm_build_308)
}
func (dm_build_310 *Dm_build_78) Dm_build_309(dm_build_311 int, dm_build_312 []byte) int {
return dm_build_310.Dm_build_265(dm_build_311, byte(len(dm_build_312))) + dm_build_310.Dm_build_301(dm_build_311+1, dm_build_312)
}
func (dm_build_314 *Dm_build_78) Dm_build_313(dm_build_315 int, dm_build_316 []byte) int {
return dm_build_314.Dm_build_269(dm_build_315, int16(len(dm_build_316))) + dm_build_314.Dm_build_301(dm_build_315+2, dm_build_316)
}
func (dm_build_318 *Dm_build_78) Dm_build_317(dm_build_319 int, dm_build_320 []byte) int {
return dm_build_318.Dm_build_301(dm_build_319, dm_build_320) + dm_build_318.Dm_build_265(dm_build_319+len(dm_build_320), 0)
}
func (dm_build_322 *Dm_build_78) Dm_build_321(dm_build_323 int, dm_build_324 string, dm_build_325 string, dm_build_326 *DmConnection) int {
return dm_build_322.Dm_build_305(dm_build_323, Dm_build_1346.Dm_build_1562(dm_build_324, dm_build_325, dm_build_326))
}
func (dm_build_328 *Dm_build_78) Dm_build_327(dm_build_329 int, dm_build_330 string, dm_build_331 string, dm_build_332 *DmConnection) int {
return dm_build_328.Dm_build_309(dm_build_329, Dm_build_1346.Dm_build_1562(dm_build_330, dm_build_331, dm_build_332))
}
func (dm_build_334 *Dm_build_78) Dm_build_333(dm_build_335 int, dm_build_336 string, dm_build_337 string, dm_build_338 *DmConnection) int {
return dm_build_334.Dm_build_313(dm_build_335, Dm_build_1346.Dm_build_1562(dm_build_336, dm_build_337, dm_build_338))
}
func (dm_build_340 *Dm_build_78) Dm_build_339(dm_build_341 int, dm_build_342 string, dm_build_343 string, dm_build_344 *DmConnection) int {
return dm_build_340.Dm_build_317(dm_build_341, Dm_build_1346.Dm_build_1562(dm_build_342, dm_build_343, dm_build_344))
}
func (dm_build_346 *Dm_build_78) Dm_build_345(dm_build_347 int) byte {
return Dm_build_1346.Dm_build_1567(dm_build_346.Dm_build_372(dm_build_347, 1))
}
func (dm_build_349 *Dm_build_78) Dm_build_348(dm_build_350 int) int16 {
return Dm_build_1346.Dm_build_1570(dm_build_349.Dm_build_372(dm_build_350, 2))
}
func (dm_build_352 *Dm_build_78) Dm_build_351(dm_build_353 int) int32 {
return Dm_build_1346.Dm_build_1573(dm_build_352.Dm_build_372(dm_build_353, 4))
}
func (dm_build_355 *Dm_build_78) Dm_build_354(dm_build_356 int) int64 {
return Dm_build_1346.Dm_build_1576(dm_build_355.Dm_build_372(dm_build_356, 8))
}
func (dm_build_358 *Dm_build_78) Dm_build_357(dm_build_359 int) float32 {
return Dm_build_1346.Dm_build_1579(dm_build_358.Dm_build_372(dm_build_359, 4))
}
func (dm_build_361 *Dm_build_78) Dm_build_360(dm_build_362 int) float64 {
return Dm_build_1346.Dm_build_1582(dm_build_361.Dm_build_372(dm_build_362, 8))
}
func (dm_build_364 *Dm_build_78) Dm_build_363(dm_build_365 int) uint8 {
return Dm_build_1346.Dm_build_1585(dm_build_364.Dm_build_372(dm_build_365, 1))
}
func (dm_build_367 *Dm_build_78) Dm_build_366(dm_build_368 int) uint16 {
return Dm_build_1346.Dm_build_1588(dm_build_367.Dm_build_372(dm_build_368, 2))
}
func (dm_build_370 *Dm_build_78) Dm_build_369(dm_build_371 int) uint32 {
return Dm_build_1346.Dm_build_1591(dm_build_370.Dm_build_372(dm_build_371, 4))
}
func (dm_build_373 *Dm_build_78) Dm_build_372(dm_build_374 int, dm_build_375 int) []byte {
return dm_build_373.dm_build_79[dm_build_374 : dm_build_374+dm_build_375]
}
func (dm_build_377 *Dm_build_78) Dm_build_376(dm_build_378 int) []byte {
dm_build_379 := dm_build_377.Dm_build_351(dm_build_378)
return dm_build_377.Dm_build_372(dm_build_378+4, int(dm_build_379))
}
func (dm_build_381 *Dm_build_78) Dm_build_380(dm_build_382 int) []byte {
dm_build_383 := dm_build_381.Dm_build_345(dm_build_382)
return dm_build_381.Dm_build_372(dm_build_382+1, int(dm_build_383))
}
func (dm_build_385 *Dm_build_78) Dm_build_384(dm_build_386 int) []byte {
dm_build_387 := dm_build_385.Dm_build_348(dm_build_386)
return dm_build_385.Dm_build_372(dm_build_386+2, int(dm_build_387))
}
func (dm_build_389 *Dm_build_78) Dm_build_388(dm_build_390 int) []byte {
dm_build_391 := 0
for dm_build_389.Dm_build_345(dm_build_390) != 0 {
dm_build_390++
dm_build_391++
}
return dm_build_389.Dm_build_372(dm_build_390-dm_build_391, int(dm_build_391))
}
func (dm_build_393 *Dm_build_78) Dm_build_392(dm_build_394 int, dm_build_395 string, dm_build_396 *DmConnection) string {
return Dm_build_1346.Dm_build_1598(dm_build_393.Dm_build_376(dm_build_394), dm_build_395, dm_build_396)
}
func (dm_build_398 *Dm_build_78) Dm_build_397(dm_build_399 int, dm_build_400 string, dm_build_401 *DmConnection) string {
return Dm_build_1346.Dm_build_1598(dm_build_398.Dm_build_380(dm_build_399), dm_build_400, dm_build_401)
}
func (dm_build_403 *Dm_build_78) Dm_build_402(dm_build_404 int, dm_build_405 string, dm_build_406 *DmConnection) string {
return Dm_build_1346.Dm_build_1598(dm_build_403.Dm_build_384(dm_build_404), dm_build_405, dm_build_406)
}
func (dm_build_408 *Dm_build_78) Dm_build_407(dm_build_409 int, dm_build_410 string, dm_build_411 *DmConnection) string {
return Dm_build_1346.Dm_build_1598(dm_build_408.Dm_build_388(dm_build_409), dm_build_410, dm_build_411)
}
+206
View File
@@ -0,0 +1,206 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"container/list"
"io"
)
type Dm_build_0 struct {
dm_build_1 *list.List
dm_build_2 *dm_build_54
dm_build_3 int
}
func Dm_build_4() *Dm_build_0 {
return &Dm_build_0{
dm_build_1: list.New(),
dm_build_3: 0,
}
}
func (dm_build_6 *Dm_build_0) Dm_build_5() int {
return dm_build_6.dm_build_3
}
func (dm_build_8 *Dm_build_0) Dm_build_7(dm_build_9 *Dm_build_78, dm_build_10 int) int {
var dm_build_11 = 0
var dm_build_12 = 0
for dm_build_11 < dm_build_10 && dm_build_8.dm_build_2 != nil {
dm_build_12 = dm_build_8.dm_build_2.dm_build_62(dm_build_9, dm_build_10-dm_build_11)
if dm_build_8.dm_build_2.dm_build_57 == 0 {
dm_build_8.dm_build_44()
}
dm_build_11 += dm_build_12
dm_build_8.dm_build_3 -= dm_build_12
}
return dm_build_11
}
func (dm_build_14 *Dm_build_0) Dm_build_13(dm_build_15 []byte, dm_build_16 int, dm_build_17 int) int {
var dm_build_18 = 0
var dm_build_19 = 0
for dm_build_18 < dm_build_17 && dm_build_14.dm_build_2 != nil {
dm_build_19 = dm_build_14.dm_build_2.dm_build_66(dm_build_15, dm_build_16, dm_build_17-dm_build_18)
if dm_build_14.dm_build_2.dm_build_57 == 0 {
dm_build_14.dm_build_44()
}
dm_build_18 += dm_build_19
dm_build_14.dm_build_3 -= dm_build_19
dm_build_16 += dm_build_19
}
return dm_build_18
}
func (dm_build_21 *Dm_build_0) Dm_build_20(dm_build_22 io.Writer, dm_build_23 int) int {
var dm_build_24 = 0
var dm_build_25 = 0
for dm_build_24 < dm_build_23 && dm_build_21.dm_build_2 != nil {
dm_build_25 = dm_build_21.dm_build_2.dm_build_71(dm_build_22, dm_build_23-dm_build_24)
if dm_build_21.dm_build_2.dm_build_57 == 0 {
dm_build_21.dm_build_44()
}
dm_build_24 += dm_build_25
dm_build_21.dm_build_3 -= dm_build_25
}
return dm_build_24
}
func (dm_build_27 *Dm_build_0) Dm_build_26(dm_build_28 []byte, dm_build_29 int, dm_build_30 int) {
if dm_build_30 == 0 {
return
}
var dm_build_31 = dm_build_58(dm_build_28, dm_build_29, dm_build_30)
if dm_build_27.dm_build_2 == nil {
dm_build_27.dm_build_2 = dm_build_31
} else {
dm_build_27.dm_build_1.PushBack(dm_build_31)
}
dm_build_27.dm_build_3 += dm_build_30
}
func (dm_build_33 *Dm_build_0) dm_build_32(dm_build_34 int) byte {
var dm_build_35 = dm_build_34
var dm_build_36 = dm_build_33.dm_build_2
for dm_build_35 > 0 && dm_build_36 != nil {
if dm_build_36.dm_build_57 == 0 {
continue
}
if dm_build_35 > dm_build_36.dm_build_57-1 {
dm_build_35 -= dm_build_36.dm_build_57
dm_build_36 = dm_build_33.dm_build_1.Front().Value.(*dm_build_54)
} else {
break
}
}
return dm_build_36.dm_build_75(dm_build_35)
}
func (dm_build_38 *Dm_build_0) Dm_build_37(dm_build_39 *Dm_build_0) {
if dm_build_39.dm_build_3 == 0 {
return
}
var dm_build_40 = dm_build_39.dm_build_2
for dm_build_40 != nil {
dm_build_38.dm_build_41(dm_build_40)
dm_build_39.dm_build_44()
dm_build_40 = dm_build_39.dm_build_2
}
dm_build_39.dm_build_3 = 0
}
func (dm_build_42 *Dm_build_0) dm_build_41(dm_build_43 *dm_build_54) {
if dm_build_43.dm_build_57 == 0 {
return
}
if dm_build_42.dm_build_2 == nil {
dm_build_42.dm_build_2 = dm_build_43
} else {
dm_build_42.dm_build_1.PushBack(dm_build_43)
}
dm_build_42.dm_build_3 += dm_build_43.dm_build_57
}
func (dm_build_45 *Dm_build_0) dm_build_44() {
var dm_build_46 = dm_build_45.dm_build_1.Front()
if dm_build_46 == nil {
dm_build_45.dm_build_2 = nil
} else {
dm_build_45.dm_build_2 = dm_build_46.Value.(*dm_build_54)
dm_build_45.dm_build_1.Remove(dm_build_46)
}
}
func (dm_build_48 *Dm_build_0) Dm_build_47() []byte {
var dm_build_49 = make([]byte, dm_build_48.dm_build_3)
var dm_build_50 = dm_build_48.dm_build_2
var dm_build_51 = 0
var dm_build_52 = len(dm_build_49)
var dm_build_53 = 0
for dm_build_50 != nil {
if dm_build_50.dm_build_57 > 0 {
if dm_build_52 > dm_build_50.dm_build_57 {
dm_build_53 = dm_build_50.dm_build_57
} else {
dm_build_53 = dm_build_52
}
copy(dm_build_49[dm_build_51:dm_build_51+dm_build_53], dm_build_50.dm_build_55[dm_build_50.dm_build_56:dm_build_50.dm_build_56+dm_build_53])
dm_build_51 += dm_build_53
dm_build_52 -= dm_build_53
}
if dm_build_48.dm_build_1.Front() == nil {
dm_build_50 = nil
} else {
dm_build_50 = dm_build_48.dm_build_1.Front().Value.(*dm_build_54)
}
}
return dm_build_49
}
type dm_build_54 struct {
dm_build_55 []byte
dm_build_56 int
dm_build_57 int
}
func dm_build_58(dm_build_59 []byte, dm_build_60 int, dm_build_61 int) *dm_build_54 {
return &dm_build_54{
dm_build_59,
dm_build_60,
dm_build_61,
}
}
func (dm_build_63 *dm_build_54) dm_build_62(dm_build_64 *Dm_build_78, dm_build_65 int) int {
if dm_build_63.dm_build_57 <= dm_build_65 {
dm_build_65 = dm_build_63.dm_build_57
}
dm_build_64.Dm_build_161(dm_build_63.dm_build_55[dm_build_63.dm_build_56 : dm_build_63.dm_build_56+dm_build_65])
dm_build_63.dm_build_56 += dm_build_65
dm_build_63.dm_build_57 -= dm_build_65
return dm_build_65
}
func (dm_build_67 *dm_build_54) dm_build_66(dm_build_68 []byte, dm_build_69 int, dm_build_70 int) int {
if dm_build_67.dm_build_57 <= dm_build_70 {
dm_build_70 = dm_build_67.dm_build_57
}
copy(dm_build_68[dm_build_69:dm_build_69+dm_build_70], dm_build_67.dm_build_55[dm_build_67.dm_build_56:dm_build_67.dm_build_56+dm_build_70])
dm_build_67.dm_build_56 += dm_build_70
dm_build_67.dm_build_57 -= dm_build_70
return dm_build_70
}
func (dm_build_72 *dm_build_54) dm_build_71(dm_build_73 io.Writer, dm_build_74 int) int {
if dm_build_72.dm_build_57 <= dm_build_74 {
dm_build_74 = dm_build_72.dm_build_57
}
dm_build_73.Write(dm_build_72.dm_build_55[dm_build_72.dm_build_56 : dm_build_72.dm_build_56+dm_build_74])
dm_build_72.dm_build_56 += dm_build_74
dm_build_72.dm_build_57 -= dm_build_74
return dm_build_74
}
func (dm_build_76 *dm_build_54) dm_build_75(dm_build_77 int) byte {
return dm_build_76.dm_build_55[dm_build_76.dm_build_56+dm_build_77]
}
+522
View File
@@ -0,0 +1,522 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"bytes"
"golang.org/x/text/encoding"
"golang.org/x/text/encoding/ianaindex"
"golang.org/x/text/transform"
"io"
"io/ioutil"
"math"
)
type dm_build_1345 struct{}
var Dm_build_1346 = &dm_build_1345{}
func (Dm_build_1348 *dm_build_1345) Dm_build_1347(dm_build_1349 []byte, dm_build_1350 int, dm_build_1351 byte) int {
dm_build_1349[dm_build_1350] = dm_build_1351
return 1
}
func (Dm_build_1353 *dm_build_1345) Dm_build_1352(dm_build_1354 []byte, dm_build_1355 int, dm_build_1356 int8) int {
dm_build_1354[dm_build_1355] = byte(dm_build_1356)
return 1
}
func (Dm_build_1358 *dm_build_1345) Dm_build_1357(dm_build_1359 []byte, dm_build_1360 int, dm_build_1361 int16) int {
dm_build_1359[dm_build_1360] = byte(dm_build_1361)
dm_build_1360++
dm_build_1359[dm_build_1360] = byte(dm_build_1361 >> 8)
return 2
}
func (Dm_build_1363 *dm_build_1345) Dm_build_1362(dm_build_1364 []byte, dm_build_1365 int, dm_build_1366 int32) int {
dm_build_1364[dm_build_1365] = byte(dm_build_1366)
dm_build_1365++
dm_build_1364[dm_build_1365] = byte(dm_build_1366 >> 8)
dm_build_1365++
dm_build_1364[dm_build_1365] = byte(dm_build_1366 >> 16)
dm_build_1365++
dm_build_1364[dm_build_1365] = byte(dm_build_1366 >> 24)
dm_build_1365++
return 4
}
func (Dm_build_1368 *dm_build_1345) Dm_build_1367(dm_build_1369 []byte, dm_build_1370 int, dm_build_1371 int64) int {
dm_build_1369[dm_build_1370] = byte(dm_build_1371)
dm_build_1370++
dm_build_1369[dm_build_1370] = byte(dm_build_1371 >> 8)
dm_build_1370++
dm_build_1369[dm_build_1370] = byte(dm_build_1371 >> 16)
dm_build_1370++
dm_build_1369[dm_build_1370] = byte(dm_build_1371 >> 24)
dm_build_1370++
dm_build_1369[dm_build_1370] = byte(dm_build_1371 >> 32)
dm_build_1370++
dm_build_1369[dm_build_1370] = byte(dm_build_1371 >> 40)
dm_build_1370++
dm_build_1369[dm_build_1370] = byte(dm_build_1371 >> 48)
dm_build_1370++
dm_build_1369[dm_build_1370] = byte(dm_build_1371 >> 56)
return 8
}
func (Dm_build_1373 *dm_build_1345) Dm_build_1372(dm_build_1374 []byte, dm_build_1375 int, dm_build_1376 float32) int {
return Dm_build_1373.Dm_build_1392(dm_build_1374, dm_build_1375, math.Float32bits(dm_build_1376))
}
func (Dm_build_1378 *dm_build_1345) Dm_build_1377(dm_build_1379 []byte, dm_build_1380 int, dm_build_1381 float64) int {
return Dm_build_1378.Dm_build_1397(dm_build_1379, dm_build_1380, math.Float64bits(dm_build_1381))
}
func (Dm_build_1383 *dm_build_1345) Dm_build_1382(dm_build_1384 []byte, dm_build_1385 int, dm_build_1386 uint8) int {
dm_build_1384[dm_build_1385] = byte(dm_build_1386)
return 1
}
func (Dm_build_1388 *dm_build_1345) Dm_build_1387(dm_build_1389 []byte, dm_build_1390 int, dm_build_1391 uint16) int {
dm_build_1389[dm_build_1390] = byte(dm_build_1391)
dm_build_1390++
dm_build_1389[dm_build_1390] = byte(dm_build_1391 >> 8)
return 2
}
func (Dm_build_1393 *dm_build_1345) Dm_build_1392(dm_build_1394 []byte, dm_build_1395 int, dm_build_1396 uint32) int {
dm_build_1394[dm_build_1395] = byte(dm_build_1396)
dm_build_1395++
dm_build_1394[dm_build_1395] = byte(dm_build_1396 >> 8)
dm_build_1395++
dm_build_1394[dm_build_1395] = byte(dm_build_1396 >> 16)
dm_build_1395++
dm_build_1394[dm_build_1395] = byte(dm_build_1396 >> 24)
return 3
}
func (Dm_build_1398 *dm_build_1345) Dm_build_1397(dm_build_1399 []byte, dm_build_1400 int, dm_build_1401 uint64) int {
dm_build_1399[dm_build_1400] = byte(dm_build_1401)
dm_build_1400++
dm_build_1399[dm_build_1400] = byte(dm_build_1401 >> 8)
dm_build_1400++
dm_build_1399[dm_build_1400] = byte(dm_build_1401 >> 16)
dm_build_1400++
dm_build_1399[dm_build_1400] = byte(dm_build_1401 >> 24)
dm_build_1400++
dm_build_1399[dm_build_1400] = byte(dm_build_1401 >> 32)
dm_build_1400++
dm_build_1399[dm_build_1400] = byte(dm_build_1401 >> 40)
dm_build_1400++
dm_build_1399[dm_build_1400] = byte(dm_build_1401 >> 48)
dm_build_1400++
dm_build_1399[dm_build_1400] = byte(dm_build_1401 >> 56)
return 3
}
func (Dm_build_1403 *dm_build_1345) Dm_build_1402(dm_build_1404 []byte, dm_build_1405 int, dm_build_1406 []byte, dm_build_1407 int, dm_build_1408 int) int {
copy(dm_build_1404[dm_build_1405:dm_build_1405+dm_build_1408], dm_build_1406[dm_build_1407:dm_build_1407+dm_build_1408])
return dm_build_1408
}
func (Dm_build_1410 *dm_build_1345) Dm_build_1409(dm_build_1411 []byte, dm_build_1412 int, dm_build_1413 []byte, dm_build_1414 int, dm_build_1415 int) int {
dm_build_1412 += Dm_build_1410.Dm_build_1392(dm_build_1411, dm_build_1412, uint32(dm_build_1415))
return 4 + Dm_build_1410.Dm_build_1402(dm_build_1411, dm_build_1412, dm_build_1413, dm_build_1414, dm_build_1415)
}
func (Dm_build_1417 *dm_build_1345) Dm_build_1416(dm_build_1418 []byte, dm_build_1419 int, dm_build_1420 []byte, dm_build_1421 int, dm_build_1422 int) int {
dm_build_1419 += Dm_build_1417.Dm_build_1387(dm_build_1418, dm_build_1419, uint16(dm_build_1422))
return 2 + Dm_build_1417.Dm_build_1402(dm_build_1418, dm_build_1419, dm_build_1420, dm_build_1421, dm_build_1422)
}
func (Dm_build_1424 *dm_build_1345) Dm_build_1423(dm_build_1425 []byte, dm_build_1426 int, dm_build_1427 string, dm_build_1428 string, dm_build_1429 *DmConnection) int {
dm_build_1430 := Dm_build_1424.Dm_build_1562(dm_build_1427, dm_build_1428, dm_build_1429)
dm_build_1426 += Dm_build_1424.Dm_build_1392(dm_build_1425, dm_build_1426, uint32(len(dm_build_1430)))
return 4 + Dm_build_1424.Dm_build_1402(dm_build_1425, dm_build_1426, dm_build_1430, 0, len(dm_build_1430))
}
func (Dm_build_1432 *dm_build_1345) Dm_build_1431(dm_build_1433 []byte, dm_build_1434 int, dm_build_1435 string, dm_build_1436 string, dm_build_1437 *DmConnection) int {
dm_build_1438 := Dm_build_1432.Dm_build_1562(dm_build_1435, dm_build_1436, dm_build_1437)
dm_build_1434 += Dm_build_1432.Dm_build_1387(dm_build_1433, dm_build_1434, uint16(len(dm_build_1438)))
return 2 + Dm_build_1432.Dm_build_1402(dm_build_1433, dm_build_1434, dm_build_1438, 0, len(dm_build_1438))
}
func (Dm_build_1440 *dm_build_1345) Dm_build_1439(dm_build_1441 []byte, dm_build_1442 int) byte {
return dm_build_1441[dm_build_1442]
}
func (Dm_build_1444 *dm_build_1345) Dm_build_1443(dm_build_1445 []byte, dm_build_1446 int) int16 {
var dm_build_1447 int16
dm_build_1447 = int16(dm_build_1445[dm_build_1446] & 0xff)
dm_build_1446++
dm_build_1447 |= int16(dm_build_1445[dm_build_1446]&0xff) << 8
return dm_build_1447
}
func (Dm_build_1449 *dm_build_1345) Dm_build_1448(dm_build_1450 []byte, dm_build_1451 int) int32 {
var dm_build_1452 int32
dm_build_1452 = int32(dm_build_1450[dm_build_1451] & 0xff)
dm_build_1451++
dm_build_1452 |= int32(dm_build_1450[dm_build_1451]&0xff) << 8
dm_build_1451++
dm_build_1452 |= int32(dm_build_1450[dm_build_1451]&0xff) << 16
dm_build_1451++
dm_build_1452 |= int32(dm_build_1450[dm_build_1451]&0xff) << 24
return dm_build_1452
}
func (Dm_build_1454 *dm_build_1345) Dm_build_1453(dm_build_1455 []byte, dm_build_1456 int) int64 {
var dm_build_1457 int64
dm_build_1457 = int64(dm_build_1455[dm_build_1456] & 0xff)
dm_build_1456++
dm_build_1457 |= int64(dm_build_1455[dm_build_1456]&0xff) << 8
dm_build_1456++
dm_build_1457 |= int64(dm_build_1455[dm_build_1456]&0xff) << 16
dm_build_1456++
dm_build_1457 |= int64(dm_build_1455[dm_build_1456]&0xff) << 24
dm_build_1456++
dm_build_1457 |= int64(dm_build_1455[dm_build_1456]&0xff) << 32
dm_build_1456++
dm_build_1457 |= int64(dm_build_1455[dm_build_1456]&0xff) << 40
dm_build_1456++
dm_build_1457 |= int64(dm_build_1455[dm_build_1456]&0xff) << 48
dm_build_1456++
dm_build_1457 |= int64(dm_build_1455[dm_build_1456]&0xff) << 56
return dm_build_1457
}
func (Dm_build_1459 *dm_build_1345) Dm_build_1458(dm_build_1460 []byte, dm_build_1461 int) float32 {
return math.Float32frombits(Dm_build_1459.Dm_build_1475(dm_build_1460, dm_build_1461))
}
func (Dm_build_1463 *dm_build_1345) Dm_build_1462(dm_build_1464 []byte, dm_build_1465 int) float64 {
return math.Float64frombits(Dm_build_1463.Dm_build_1480(dm_build_1464, dm_build_1465))
}
func (Dm_build_1467 *dm_build_1345) Dm_build_1466(dm_build_1468 []byte, dm_build_1469 int) uint8 {
return uint8(dm_build_1468[dm_build_1469] & 0xff)
}
func (Dm_build_1471 *dm_build_1345) Dm_build_1470(dm_build_1472 []byte, dm_build_1473 int) uint16 {
var dm_build_1474 uint16
dm_build_1474 = uint16(dm_build_1472[dm_build_1473] & 0xff)
dm_build_1473++
dm_build_1474 |= uint16(dm_build_1472[dm_build_1473]&0xff) << 8
return dm_build_1474
}
func (Dm_build_1476 *dm_build_1345) Dm_build_1475(dm_build_1477 []byte, dm_build_1478 int) uint32 {
var dm_build_1479 uint32
dm_build_1479 = uint32(dm_build_1477[dm_build_1478] & 0xff)
dm_build_1478++
dm_build_1479 |= uint32(dm_build_1477[dm_build_1478]&0xff) << 8
dm_build_1478++
dm_build_1479 |= uint32(dm_build_1477[dm_build_1478]&0xff) << 16
dm_build_1478++
dm_build_1479 |= uint32(dm_build_1477[dm_build_1478]&0xff) << 24
return dm_build_1479
}
func (Dm_build_1481 *dm_build_1345) Dm_build_1480(dm_build_1482 []byte, dm_build_1483 int) uint64 {
var dm_build_1484 uint64
dm_build_1484 = uint64(dm_build_1482[dm_build_1483] & 0xff)
dm_build_1483++
dm_build_1484 |= uint64(dm_build_1482[dm_build_1483]&0xff) << 8
dm_build_1483++
dm_build_1484 |= uint64(dm_build_1482[dm_build_1483]&0xff) << 16
dm_build_1483++
dm_build_1484 |= uint64(dm_build_1482[dm_build_1483]&0xff) << 24
dm_build_1483++
dm_build_1484 |= uint64(dm_build_1482[dm_build_1483]&0xff) << 32
dm_build_1483++
dm_build_1484 |= uint64(dm_build_1482[dm_build_1483]&0xff) << 40
dm_build_1483++
dm_build_1484 |= uint64(dm_build_1482[dm_build_1483]&0xff) << 48
dm_build_1483++
dm_build_1484 |= uint64(dm_build_1482[dm_build_1483]&0xff) << 56
return dm_build_1484
}
func (Dm_build_1486 *dm_build_1345) Dm_build_1485(dm_build_1487 []byte, dm_build_1488 int) []byte {
dm_build_1489 := Dm_build_1486.Dm_build_1475(dm_build_1487, dm_build_1488)
dm_build_1490 := make([]byte, dm_build_1489)
copy(dm_build_1490[:int(dm_build_1489)], dm_build_1487[dm_build_1488+4:dm_build_1488+4+int(dm_build_1489)])
return dm_build_1490
}
func (Dm_build_1492 *dm_build_1345) Dm_build_1491(dm_build_1493 []byte, dm_build_1494 int) []byte {
dm_build_1495 := Dm_build_1492.Dm_build_1470(dm_build_1493, dm_build_1494)
dm_build_1496 := make([]byte, dm_build_1495)
copy(dm_build_1496[:int(dm_build_1495)], dm_build_1493[dm_build_1494+2:dm_build_1494+2+int(dm_build_1495)])
return dm_build_1496
}
func (Dm_build_1498 *dm_build_1345) Dm_build_1497(dm_build_1499 []byte, dm_build_1500 int, dm_build_1501 int) []byte {
dm_build_1502 := make([]byte, dm_build_1501)
copy(dm_build_1502[:dm_build_1501], dm_build_1499[dm_build_1500:dm_build_1500+dm_build_1501])
return dm_build_1502
}
func (Dm_build_1504 *dm_build_1345) Dm_build_1503(dm_build_1505 []byte, dm_build_1506 int, dm_build_1507 int, dm_build_1508 string, dm_build_1509 *DmConnection) string {
return Dm_build_1504.Dm_build_1598(dm_build_1505[dm_build_1506:dm_build_1506+dm_build_1507], dm_build_1508, dm_build_1509)
}
func (Dm_build_1511 *dm_build_1345) Dm_build_1510(dm_build_1512 []byte, dm_build_1513 int, dm_build_1514 string, dm_build_1515 *DmConnection) string {
dm_build_1516 := Dm_build_1511.Dm_build_1475(dm_build_1512, dm_build_1513)
dm_build_1513 += 4
return Dm_build_1511.Dm_build_1503(dm_build_1512, dm_build_1513, int(dm_build_1516), dm_build_1514, dm_build_1515)
}
func (Dm_build_1518 *dm_build_1345) Dm_build_1517(dm_build_1519 []byte, dm_build_1520 int, dm_build_1521 string, dm_build_1522 *DmConnection) string {
dm_build_1523 := Dm_build_1518.Dm_build_1470(dm_build_1519, dm_build_1520)
dm_build_1520 += 2
return Dm_build_1518.Dm_build_1503(dm_build_1519, dm_build_1520, int(dm_build_1523), dm_build_1521, dm_build_1522)
}
func (Dm_build_1525 *dm_build_1345) Dm_build_1524(dm_build_1526 byte) []byte {
return []byte{dm_build_1526}
}
func (Dm_build_1528 *dm_build_1345) Dm_build_1527(dm_build_1529 int8) []byte {
return []byte{byte(dm_build_1529)}
}
func (Dm_build_1531 *dm_build_1345) Dm_build_1530(dm_build_1532 int16) []byte {
return []byte{byte(dm_build_1532), byte(dm_build_1532 >> 8)}
}
func (Dm_build_1534 *dm_build_1345) Dm_build_1533(dm_build_1535 int32) []byte {
return []byte{byte(dm_build_1535), byte(dm_build_1535 >> 8), byte(dm_build_1535 >> 16), byte(dm_build_1535 >> 24)}
}
func (Dm_build_1537 *dm_build_1345) Dm_build_1536(dm_build_1538 int64) []byte {
return []byte{byte(dm_build_1538), byte(dm_build_1538 >> 8), byte(dm_build_1538 >> 16), byte(dm_build_1538 >> 24), byte(dm_build_1538 >> 32),
byte(dm_build_1538 >> 40), byte(dm_build_1538 >> 48), byte(dm_build_1538 >> 56)}
}
func (Dm_build_1540 *dm_build_1345) Dm_build_1539(dm_build_1541 float32) []byte {
return Dm_build_1540.Dm_build_1551(math.Float32bits(dm_build_1541))
}
func (Dm_build_1543 *dm_build_1345) Dm_build_1542(dm_build_1544 float64) []byte {
return Dm_build_1543.Dm_build_1554(math.Float64bits(dm_build_1544))
}
func (Dm_build_1546 *dm_build_1345) Dm_build_1545(dm_build_1547 uint8) []byte {
return []byte{byte(dm_build_1547)}
}
func (Dm_build_1549 *dm_build_1345) Dm_build_1548(dm_build_1550 uint16) []byte {
return []byte{byte(dm_build_1550), byte(dm_build_1550 >> 8)}
}
func (Dm_build_1552 *dm_build_1345) Dm_build_1551(dm_build_1553 uint32) []byte {
return []byte{byte(dm_build_1553), byte(dm_build_1553 >> 8), byte(dm_build_1553 >> 16), byte(dm_build_1553 >> 24)}
}
func (Dm_build_1555 *dm_build_1345) Dm_build_1554(dm_build_1556 uint64) []byte {
return []byte{byte(dm_build_1556), byte(dm_build_1556 >> 8), byte(dm_build_1556 >> 16), byte(dm_build_1556 >> 24), byte(dm_build_1556 >> 32), byte(dm_build_1556 >> 40), byte(dm_build_1556 >> 48), byte(dm_build_1556 >> 56)}
}
func (Dm_build_1558 *dm_build_1345) Dm_build_1557(dm_build_1559 []byte, dm_build_1560 string, dm_build_1561 *DmConnection) []byte {
if dm_build_1560 == "UTF-8" {
return dm_build_1559
}
if dm_build_1561 == nil {
if e := dm_build_1603(dm_build_1560); e != nil {
tmp, err := ioutil.ReadAll(
transform.NewReader(bytes.NewReader(dm_build_1559), e.NewEncoder()),
)
if err != nil {
panic("UTF8 To Charset error!")
}
return tmp
}
panic("Unsupported Charset!")
}
if dm_build_1561.encodeBuffer == nil {
dm_build_1561.encodeBuffer = bytes.NewBuffer(nil)
dm_build_1561.encode = dm_build_1603(dm_build_1561.getServerEncoding())
dm_build_1561.transformReaderDst = make([]byte, 4096)
dm_build_1561.transformReaderSrc = make([]byte, 4096)
}
if e := dm_build_1561.encode; e != nil {
dm_build_1561.encodeBuffer.Reset()
n, err := dm_build_1561.encodeBuffer.ReadFrom(
Dm_build_1617(bytes.NewReader(dm_build_1559), e.NewEncoder(), dm_build_1561.transformReaderDst, dm_build_1561.transformReaderSrc),
)
if err != nil {
panic("UTF8 To Charset error!")
}
var tmp = make([]byte, n)
if _, err = dm_build_1561.encodeBuffer.Read(tmp); err != nil {
panic("UTF8 To Charset error!")
}
return tmp
}
panic("Unsupported Charset!")
}
func (Dm_build_1563 *dm_build_1345) Dm_build_1562(dm_build_1564 string, dm_build_1565 string, dm_build_1566 *DmConnection) []byte {
return Dm_build_1563.Dm_build_1557([]byte(dm_build_1564), dm_build_1565, dm_build_1566)
}
func (Dm_build_1568 *dm_build_1345) Dm_build_1567(dm_build_1569 []byte) byte {
return Dm_build_1568.Dm_build_1439(dm_build_1569, 0)
}
func (Dm_build_1571 *dm_build_1345) Dm_build_1570(dm_build_1572 []byte) int16 {
return Dm_build_1571.Dm_build_1443(dm_build_1572, 0)
}
func (Dm_build_1574 *dm_build_1345) Dm_build_1573(dm_build_1575 []byte) int32 {
return Dm_build_1574.Dm_build_1448(dm_build_1575, 0)
}
func (Dm_build_1577 *dm_build_1345) Dm_build_1576(dm_build_1578 []byte) int64 {
return Dm_build_1577.Dm_build_1453(dm_build_1578, 0)
}
func (Dm_build_1580 *dm_build_1345) Dm_build_1579(dm_build_1581 []byte) float32 {
return Dm_build_1580.Dm_build_1458(dm_build_1581, 0)
}
func (Dm_build_1583 *dm_build_1345) Dm_build_1582(dm_build_1584 []byte) float64 {
return Dm_build_1583.Dm_build_1462(dm_build_1584, 0)
}
func (Dm_build_1586 *dm_build_1345) Dm_build_1585(dm_build_1587 []byte) uint8 {
return Dm_build_1586.Dm_build_1466(dm_build_1587, 0)
}
func (Dm_build_1589 *dm_build_1345) Dm_build_1588(dm_build_1590 []byte) uint16 {
return Dm_build_1589.Dm_build_1470(dm_build_1590, 0)
}
func (Dm_build_1592 *dm_build_1345) Dm_build_1591(dm_build_1593 []byte) uint32 {
return Dm_build_1592.Dm_build_1475(dm_build_1593, 0)
}
func (Dm_build_1595 *dm_build_1345) Dm_build_1594(dm_build_1596 []byte, dm_build_1597 string) []byte {
if dm_build_1597 == "UTF-8" {
return dm_build_1596
}
if e := dm_build_1603(dm_build_1597); e != nil {
tmp, err := ioutil.ReadAll(
transform.NewReader(bytes.NewReader(dm_build_1596), e.NewDecoder()),
)
if err != nil {
panic("Charset To UTF8 error!")
}
return tmp
}
panic("Unsupported Charset!")
}
func (Dm_build_1599 *dm_build_1345) Dm_build_1598(dm_build_1600 []byte, dm_build_1601 string, dm_build_1602 *DmConnection) string {
return string(Dm_build_1599.Dm_build_1594(dm_build_1600, dm_build_1601))
}
func dm_build_1603(dm_build_1604 string) encoding.Encoding {
if e, err := ianaindex.MIB.Encoding(dm_build_1604); err == nil && e != nil {
return e
}
return nil
}
type Dm_build_1605 struct {
dm_build_1606 io.Reader
dm_build_1607 transform.Transformer
dm_build_1608 error
dm_build_1609 []byte
dm_build_1610, dm_build_1611 int
dm_build_1612 []byte
dm_build_1613, dm_build_1614 int
dm_build_1615 bool
}
const dm_build_1616 = 4096
func Dm_build_1617(dm_build_1618 io.Reader, dm_build_1619 transform.Transformer, dm_build_1620 []byte, dm_build_1621 []byte) *Dm_build_1605 {
dm_build_1619.Reset()
return &Dm_build_1605{
dm_build_1606: dm_build_1618,
dm_build_1607: dm_build_1619,
dm_build_1609: dm_build_1620,
dm_build_1612: dm_build_1621,
}
}
func (dm_build_1623 *Dm_build_1605) Read(dm_build_1624 []byte) (int, error) {
dm_build_1625, dm_build_1626 := 0, error(nil)
for {
if dm_build_1623.dm_build_1610 != dm_build_1623.dm_build_1611 {
dm_build_1625 = copy(dm_build_1624, dm_build_1623.dm_build_1609[dm_build_1623.dm_build_1610:dm_build_1623.dm_build_1611])
dm_build_1623.dm_build_1610 += dm_build_1625
if dm_build_1623.dm_build_1610 == dm_build_1623.dm_build_1611 && dm_build_1623.dm_build_1615 {
return dm_build_1625, dm_build_1623.dm_build_1608
}
return dm_build_1625, nil
} else if dm_build_1623.dm_build_1615 {
return 0, dm_build_1623.dm_build_1608
}
if dm_build_1623.dm_build_1613 != dm_build_1623.dm_build_1614 || dm_build_1623.dm_build_1608 != nil {
dm_build_1623.dm_build_1610 = 0
dm_build_1623.dm_build_1611, dm_build_1625, dm_build_1626 = dm_build_1623.dm_build_1607.Transform(dm_build_1623.dm_build_1609, dm_build_1623.dm_build_1612[dm_build_1623.dm_build_1613:dm_build_1623.dm_build_1614], dm_build_1623.dm_build_1608 == io.EOF)
dm_build_1623.dm_build_1613 += dm_build_1625
switch {
case dm_build_1626 == nil:
if dm_build_1623.dm_build_1613 != dm_build_1623.dm_build_1614 {
dm_build_1623.dm_build_1608 = nil
}
dm_build_1623.dm_build_1615 = dm_build_1623.dm_build_1608 != nil
continue
case dm_build_1626 == transform.ErrShortDst && (dm_build_1623.dm_build_1611 != 0 || dm_build_1625 != 0):
continue
case dm_build_1626 == transform.ErrShortSrc && dm_build_1623.dm_build_1614-dm_build_1623.dm_build_1613 != len(dm_build_1623.dm_build_1612) && dm_build_1623.dm_build_1608 == nil:
default:
dm_build_1623.dm_build_1615 = true
if dm_build_1623.dm_build_1608 == nil || dm_build_1623.dm_build_1608 == io.EOF {
dm_build_1623.dm_build_1608 = dm_build_1626
}
continue
}
}
if dm_build_1623.dm_build_1613 != 0 {
dm_build_1623.dm_build_1613, dm_build_1623.dm_build_1614 = 0, copy(dm_build_1623.dm_build_1612, dm_build_1623.dm_build_1612[dm_build_1623.dm_build_1613:dm_build_1623.dm_build_1614])
}
dm_build_1625, dm_build_1623.dm_build_1608 = dm_build_1623.dm_build_1606.Read(dm_build_1623.dm_build_1612[dm_build_1623.dm_build_1614:])
dm_build_1623.dm_build_1614 += dm_build_1625
}
}
+47
View File
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"bytes"
"compress/zlib"
"github.com/golang/snappy"
)
func Compress(srcBuffer *Dm_build_78, offset int, length int, compressID int) ([]byte, error) {
if compressID == Dm_build_786 {
return snappy.Encode(nil, srcBuffer.Dm_build_372(offset, length)), nil
}
return GzlibCompress(srcBuffer, offset, length)
}
func UnCompress(srcBytes []byte, compressID int) ([]byte, error) {
if compressID == Dm_build_786 {
return snappy.Decode(nil, srcBytes)
}
return GzlibUncompress(srcBytes)
}
func GzlibCompress(srcBuffer *Dm_build_78, offset int, length int) ([]byte, error) {
var ret bytes.Buffer
var w = zlib.NewWriter(&ret)
w.Write(srcBuffer.Dm_build_372(offset, length))
w.Close()
return ret.Bytes(), nil
}
func GzlibUncompress(srcBytes []byte) ([]byte, error) {
var bytesBuf = new(bytes.Buffer)
r, err := zlib.NewReader(bytes.NewReader(srcBytes))
if err != nil {
return nil, err
}
defer r.Close()
_, err = bytesBuf.ReadFrom(r)
if err != nil {
return nil, err
}
return bytesBuf.Bytes(), nil
}
+2158
View File
File diff suppressed because it is too large Load Diff
+8
View File
@@ -0,0 +1,8 @@
module gitee.com/chunanyong/dm
go 1.13
require (
github.com/golang/snappy v0.0.1
golang.org/x/text v0.3.2
)
+5
View File
@@ -0,0 +1,5 @@
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+923
View File
@@ -0,0 +1,923 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"math"
"strconv"
"strings"
"time"
"unicode"
)
func encodeByString(x string, column column, conn DmConnection) ([]byte, error) {
dt := make([]int, DT_LEN)
if _, err := toDTFromString(x, dt); err != nil {
return nil, err
}
return encode(dt, column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
}
func encodeByTime(x time.Time, column column, conn DmConnection) ([]byte, error) {
dt := toDTFromTime(x)
return encode(dt, column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
}
func toTimeFromString(str string, ltz int) time.Time {
dt := make([]int, DT_LEN)
toDTFromString(str, dt)
return toTimeFromDT(dt, ltz)
}
func toTimeFromDT(dt []int, ltz int) time.Time {
var year, month, day, hour, minute, second, nsec, tz int
year = dt[OFFSET_YEAR]
if dt[OFFSET_MONTH] > 0 {
month = dt[OFFSET_MONTH]
} else {
month = 1
}
if dt[OFFSET_DAY] > 0 {
day = dt[OFFSET_DAY]
} else {
day = 1
}
hour = dt[OFFSET_HOUR]
minute = dt[OFFSET_MINUTE]
second = dt[OFFSET_SECOND]
nsec = dt[OFFSET_NANOSECOND]
if dt[OFFSET_TIMEZONE] == INVALID_VALUE {
tz = ltz * 60
} else {
tz = dt[OFFSET_TIMEZONE] * 60
}
return time.Date(year, time.Month(month), day, hour, minute, second, nsec, time.FixedZone("", tz))
}
func decode(value []byte, isBdta bool, column column, ltz int, dtz int) []int {
var dt []int
if isBdta {
dt = dmdtDecodeBdta(value)
} else {
dt = dmdtDecodeFast(value)
}
if column.mask == MASK_LOCAL_DATETIME {
transformTZ(dt, dtz, ltz)
}
return dt
}
func dmdtDecodeFast(value []byte) []int {
dt := make([]int, DT_LEN)
dt[OFFSET_TIMEZONE] = INVALID_VALUE
dtype := 0
if len(value) == DATE_PREC {
dtype = DATE
} else if len(value) == TIME_PREC {
dtype = TIME
} else if len(value) == TIME_TZ_PREC {
dtype = TIME_TZ
} else if len(value) == DATETIME_PREC {
dtype = DATETIME
} else if len(value) == DATETIME2_PREC {
dtype = DATETIME2
} else if len(value) == DATETIME_TZ_PREC {
dtype = DATETIME_TZ
} else if len(value) == DATETIME2_TZ_PREC {
dtype = DATETIME2_TZ
}
if dtype == DATE {
dt[OFFSET_YEAR] = int(Dm_build_1346.Dm_build_1443(value, 0)) & 0x7FFF
if dt[OFFSET_YEAR] > 9999 {
dt[OFFSET_YEAR] = int(int16(dt[OFFSET_YEAR] | 0x8000))
}
dt[OFFSET_MONTH] = ((int(value[1]) >> 7) & 0x1) + ((int(value[2]) & 0x07) << 1)
dt[OFFSET_DAY] = ((int(value[2]) & 0xF8) >> 3) & 0x1f
} else if dtype == TIME {
dt[OFFSET_HOUR] = int(value[0]) & 0x1F
dt[OFFSET_MINUTE] = ((int(value[0]) >> 5) & 0x07) + ((int(value[1]) & 0x07) << 3)
dt[OFFSET_SECOND] = ((int(value[1]) >> 3) & 0x1f) + ((int(value[2]) & 0x01) << 5)
dt[OFFSET_NANOSECOND] = ((int(value[2]) >> 1) & 0x7f) + ((int(value[3]) & 0x00ff) << 7) + ((int(value[4]) & 0x1F) << 15)
dt[OFFSET_NANOSECOND] *= 1000
} else if dtype == TIME_TZ {
dt[OFFSET_HOUR] = int(value[0]) & 0x1F
dt[OFFSET_MINUTE] = ((int(value[0]) >> 5) & 0x07) + ((int(value[1]) & 0x07) << 3)
dt[OFFSET_SECOND] = ((int(value[1]) >> 3) & 0x1f) + ((int(value[2]) & 0x01) << 5)
dt[OFFSET_NANOSECOND] = ((int(value[2]) >> 1) & 0x7f) + ((int(value[3]) & 0x00ff) << 7) + ((int(value[4]) & 0x1F) << 15)
dt[OFFSET_NANOSECOND] *= 1000
dt[OFFSET_TIMEZONE] = int(Dm_build_1346.Dm_build_1443(value, 5))
} else if dtype == DATETIME {
dt[OFFSET_YEAR] = int(Dm_build_1346.Dm_build_1443(value, 0)) & 0x7FFF
if dt[OFFSET_YEAR] > 9999 {
dt[OFFSET_YEAR] = int(int16(dt[OFFSET_YEAR] | 0x8000))
}
dt[OFFSET_MONTH] = ((int(value[1]) >> 7) & 0x1) + ((int(value[2]) & 0x07) << 1)
dt[OFFSET_DAY] = ((int(value[2]) & 0xF8) >> 3) & 0x1f
dt[OFFSET_HOUR] = (int(value[3]) & 0x1F)
dt[OFFSET_MINUTE] = ((int(value[3]) >> 5) & 0x07) + ((int(value[4]) & 0x07) << 3)
dt[OFFSET_SECOND] = ((int(value[4]) >> 3) & 0x1f) + ((int(value[5]) & 0x01) << 5)
dt[OFFSET_NANOSECOND] = ((int(value[5]) >> 1) & 0x7f) + ((int(value[6]) & 0x00ff) << 7) + ((int(value[7]) & 0x1F) << 15)
dt[OFFSET_NANOSECOND] *= 1000
} else if dtype == DATETIME_TZ {
dt[OFFSET_YEAR] = int(Dm_build_1346.Dm_build_1443(value, 0)) & 0x7FFF
if dt[OFFSET_YEAR] > 9999 {
dt[OFFSET_YEAR] = int(int16(dt[OFFSET_YEAR] | 0x8000))
}
dt[OFFSET_MONTH] = ((int(value[1]) >> 7) & 0x1) + ((int(value[2]) & 0x07) << 1)
dt[OFFSET_DAY] = ((int(value[2]) & 0xF8) >> 3) & 0x1f
dt[OFFSET_HOUR] = (int(value[3]) & 0x1F)
dt[OFFSET_MINUTE] = ((int(value[3]) >> 5) & 0x07) + ((int(value[4]) & 0x07) << 3)
dt[OFFSET_SECOND] = ((int(value[4]) >> 3) & 0x1f) + ((int(value[5]) & 0x01) << 5)
dt[OFFSET_NANOSECOND] = ((int(value[5]) >> 1) & 0x7f) + ((int(value[6]) & 0x00ff) << 7) + ((int(value[7]) & 0x1F) << 15)
dt[OFFSET_NANOSECOND] *= 1000
dt[OFFSET_TIMEZONE] = int(Dm_build_1346.Dm_build_1443(value, len(value)-2))
} else if dtype == DATETIME2 {
dt[OFFSET_YEAR] = int(Dm_build_1346.Dm_build_1443(value, 0)) & 0x7FFF
if dt[OFFSET_YEAR] > 9999 {
dt[OFFSET_YEAR] = int(int16(dt[OFFSET_YEAR] | 0x8000))
}
dt[OFFSET_MONTH] = ((int(value[1]) >> 7) & 0x1) + ((int(value[2]) & 0x07) << 1)
dt[OFFSET_DAY] = ((int(value[2]) & 0xF8) >> 3) & 0x1f
dt[OFFSET_HOUR] = (int(value[3]) & 0x1F)
dt[OFFSET_MINUTE] = ((int(value[3]) >> 5) & 0x07) + ((int(value[4]) & 0x07) << 3)
dt[OFFSET_SECOND] = ((int(value[4]) >> 3) & 0x1f) + ((int(value[5]) & 0x01) << 5)
dt[OFFSET_NANOSECOND] = ((int(value[5]) >> 1) & 0x7f) + ((int(value[6]) & 0x00ff) << 7) + ((int(value[7]) & 0x00ff) << 15) + ((int(value[8]) & 0x7F) << 23)
} else if dtype == DATETIME2_TZ {
dt[OFFSET_YEAR] = int(Dm_build_1346.Dm_build_1443(value, 0)) & 0x7FFF
if dt[OFFSET_YEAR] > 9999 {
dt[OFFSET_YEAR] = int(int16(dt[OFFSET_YEAR] | 0x8000))
}
dt[OFFSET_MONTH] = ((int(value[1]) >> 7) & 0x1) + ((int(value[2]) & 0x07) << 1)
dt[OFFSET_DAY] = ((int(value[2]) & 0xF8) >> 3) & 0x1f
dt[OFFSET_HOUR] = (int(value[3]) & 0x1F)
dt[OFFSET_MINUTE] = ((int(value[3]) >> 5) & 0x07) + ((int(value[4]) & 0x07) << 3)
dt[OFFSET_SECOND] = ((int(value[4]) >> 3) & 0x1f) + ((int(value[5]) & 0x01) << 5)
dt[OFFSET_NANOSECOND] = ((int(value[5]) >> 1) & 0x7f) + ((int(value[6]) & 0x00ff) << 7) + ((int(value[7]) & 0x00ff) << 15) + ((int(value[8]) & 0x7F) << 23)
dt[OFFSET_TIMEZONE] = int(Dm_build_1346.Dm_build_1443(value, len(value)-2))
}
return dt
}
func dmdtDecodeBdta(value []byte) []int {
dt := make([]int, DT_LEN)
dt[OFFSET_YEAR] = int(Dm_build_1346.Dm_build_1443(value, 0))
dt[OFFSET_MONTH] = int(value[2] & 0xFF)
dt[OFFSET_DAY] = int(value[3] & 0xFF)
dt[OFFSET_HOUR] = int(value[4] & 0xFF)
dt[OFFSET_MINUTE] = int(value[5] & 0xFF)
dt[OFFSET_SECOND] = int(value[6] & 0xFF)
dt[OFFSET_NANOSECOND] = int((value[7] & 0xFF) + (value[8] << 8) + (value[9] << 16))
dt[OFFSET_TIMEZONE] = int(Dm_build_1346.Dm_build_1443(value, 10))
if len(value) > 12 {
dt[OFFSET_NANOSECOND] += int(value[12] << 24)
}
return dt
}
func dtToStringByOracleFormat(dt []int, oracleFormatPattern string, scale int32, language int) string {
return format(dt, oracleFormatPattern, scale, language)
}
func dtToString(dt []int, dtype int, scale int) string {
switch dtype {
case DATE:
return formatYear(dt[OFFSET_YEAR]) + "-" + format2(dt[OFFSET_MONTH]) + "-" + format2(dt[OFFSET_DAY])
case TIME:
if scale > 0 {
return format2(dt[OFFSET_HOUR]) + ":" + format2(dt[OFFSET_MINUTE]) + ":" + format2(dt[OFFSET_SECOND]) + "." + formatMilliSecond(dt[OFFSET_NANOSECOND], scale)
} else {
return format2(dt[OFFSET_HOUR]) + ":" + format2(dt[OFFSET_MINUTE]) + ":" + format2(dt[OFFSET_SECOND])
}
case TIME_TZ:
if scale > 0 {
return format2(dt[OFFSET_HOUR]) + ":" + format2(dt[OFFSET_MINUTE]) + ":" + format2(dt[OFFSET_SECOND]) + "." + formatMilliSecond(dt[OFFSET_NANOSECOND], scale) + " " + formatTZ(dt[OFFSET_TIMEZONE])
} else {
return format2(dt[OFFSET_HOUR]) + ":" + format2(dt[OFFSET_MINUTE]) + ":" + format2(dt[OFFSET_SECOND]) + " " + formatTZ(dt[OFFSET_TIMEZONE])
}
case DATETIME, DATETIME2:
if scale > 0 {
return formatYear(dt[OFFSET_YEAR]) + "-" + format2(dt[OFFSET_MONTH]) + "-" + format2(dt[OFFSET_DAY]) + " " + format2(dt[OFFSET_HOUR]) + ":" + format2(dt[OFFSET_MINUTE]) + ":" + format2(dt[OFFSET_SECOND]) + "." + formatMilliSecond(dt[OFFSET_NANOSECOND], scale)
} else {
return formatYear(dt[OFFSET_YEAR]) + "-" + format2(dt[OFFSET_MONTH]) + "-" + format2(dt[OFFSET_DAY]) + " " + format2(dt[OFFSET_HOUR]) + ":" + format2(dt[OFFSET_MINUTE]) + ":" + format2(dt[OFFSET_SECOND])
}
case DATETIME_TZ, DATETIME2_TZ:
if scale > 0 {
return formatYear(dt[OFFSET_YEAR]) + "-" + format2(dt[OFFSET_MONTH]) + "-" + format2(dt[OFFSET_DAY]) + " " + format2(dt[OFFSET_HOUR]) + ":" + format2(dt[OFFSET_MINUTE]) + ":" + format2(dt[OFFSET_SECOND]) + "." + formatMilliSecond(dt[OFFSET_NANOSECOND], scale) + " " + formatTZ(dt[OFFSET_TIMEZONE])
} else {
return formatYear(dt[OFFSET_YEAR]) + "-" + format2(dt[OFFSET_MONTH]) + "-" + format2(dt[OFFSET_DAY]) + " " + format2(dt[OFFSET_HOUR]) + ":" + format2(dt[OFFSET_MINUTE]) + ":" + format2(dt[OFFSET_SECOND]) + " " + formatTZ(dt[OFFSET_TIMEZONE])
}
}
return ""
}
func formatYear(value int) string {
if value >= 0 {
if value < 10 {
return "000" + strconv.FormatInt(int64(value), 10)
} else if value < 100 {
return "00" + strconv.FormatInt(int64(value), 10)
} else if value < 1000 {
return "0" + strconv.FormatInt(int64(value), 10)
} else {
return strconv.FormatInt(int64(value), 10)
}
} else {
if value > -10 {
return "-000" + strconv.FormatInt(int64(-value), 10)
} else if value > -100 {
return "-00" + strconv.FormatInt(int64(-value), 10)
} else if value > -1000 {
return "-0" + strconv.FormatInt(int64(-value), 10)
} else {
return strconv.FormatInt(int64(value), 10)
}
}
}
func format2(value int) string {
if value < 10 {
return "0" + strconv.FormatInt(int64(value), 10)
} else {
return strconv.FormatInt(int64(value), 10)
}
}
func formatMilliSecond(ms int, prec int) string {
var ret string
if ms < 10 {
ret = "00000000" + strconv.FormatInt(int64(ms), 10)
} else if ms < 100 {
ret = "0000000" + strconv.FormatInt(int64(ms), 10)
} else if ms < 1000 {
ret = "000000" + strconv.FormatInt(int64(ms), 10)
} else if ms < 10000 {
ret = "00000" + strconv.FormatInt(int64(ms), 10)
} else if ms < 100000 {
ret = "0000" + strconv.FormatInt(int64(ms), 10)
} else if ms < 1000000 {
ret = "000" + strconv.FormatInt(int64(ms), 10)
} else if ms < 10000000 {
ret = "00" + strconv.FormatInt(int64(ms), 10)
} else if ms < 100000000 {
ret = "0" + strconv.FormatInt(int64(ms), 10)
} else {
ret = strconv.FormatInt(int64(ms), 10)
}
if prec < NANOSECOND_DIGITS {
ret = ret[:prec]
}
return ret
}
func formatTZ(tz int) string {
tz_hour := int(math.Abs(float64(tz / 60)))
tz_min := int(math.Abs(float64(tz % 60)))
if tz >= 0 {
return "+" + format2(tz_hour) + ":" + format2(tz_min)
} else {
return "-" + format2(tz_hour) + ":" + format2(tz_min)
}
}
func toDTFromTime(x time.Time) []int {
hour, min, sec := x.Clock()
ts := make([]int, DT_LEN)
ts[OFFSET_YEAR] = x.Year()
ts[OFFSET_MONTH] = int(x.Month())
ts[OFFSET_DAY] = x.Day()
ts[OFFSET_HOUR] = hour
ts[OFFSET_MINUTE] = min
ts[OFFSET_SECOND] = sec
ts[OFFSET_NANOSECOND] = (int)(x.Nanosecond())
_, tz := x.Zone()
ts[OFFSET_TIMEZONE] = tz / 60
return ts
}
func toDTFromUnix(sec int64, nsec int64) []int {
return toDTFromTime(time.Unix(sec, nsec))
}
func toDTFromString(s string, dt []int) (dtype int, err error) {
defer func() {
if p := recover(); p != nil {
err = ECGO_INVALID_DATETIME_FORMAT.throw()
}
}()
date_s := ""
time_s := ""
nanos_s := ""
tz_s := ""
year := 0
month := 0
day := 0
hour := 0
minute := 0
second := 0
a_nanos := 0
firstDash := -1
secondDash := -1
firstColon := -1
secondColon := -1
period := -1
sign := 0
ownTz := INVALID_VALUE
dtype = -1
zeros := "000000000"
if s != "" && strings.TrimSpace(s) == "" {
return 0, ECGO_INVALID_DATETIME_FORMAT.throw()
}
s = strings.TrimSpace(s)
if strings.Index(s, "-") == 0 {
s = strings.TrimSpace(s[1:])
sign = 1
}
comps := strings.Split(s, " ")
switch len(comps) {
case 3:
date_s = comps[0]
time_s = comps[1]
tz_s = comps[2]
dtype = DATETIME_TZ
case 2:
if strings.Index(comps[0], ":") > 0 {
time_s = comps[0]
tz_s = comps[1]
dtype = TIME_TZ
} else {
date_s = comps[0]
time_s = comps[1]
dtype = DATETIME
}
case 1:
if strings.Index(comps[0], ":") > 0 {
time_s = comps[0]
dtype = TIME
} else {
date_s = comps[0]
dtype = DATE
}
default:
return 0, ECGO_INVALID_DATETIME_FORMAT.throw()
}
if date_s != "" {
firstDash = strings.Index(date_s, "-")
secondDash = strings.Index(date_s[firstDash+1:], "-")
if firstDash < 0 || secondDash < 0 {
firstDash = strings.Index(s, ".")
secondDash = strings.Index(date_s[firstDash+1:], ".")
}
if firstDash < 0 || secondDash < 0 {
firstDash = strings.Index(s, "/")
secondDash = strings.Index(date_s[firstDash+1:], "/")
}
if secondDash > 0 {
secondDash += firstDash + 1
}
if (firstDash > 0) && (secondDash > 0) && (secondDash < len(date_s)-1) {
if sign == 1 {
i, err := strconv.ParseInt(date_s[:firstDash], 10, 32)
if err != nil {
return 0, ECGO_INVALID_DATETIME_FORMAT.addDetailln(err.Error()).throw()
}
year = 0 - int(i) - 1900
} else {
i, err := strconv.ParseInt(date_s[:firstDash], 10, 32)
if err != nil {
return 0, ECGO_INVALID_DATETIME_FORMAT.addDetailln(err.Error()).throw()
}
year = int(i) - 1900
}
i, err := strconv.ParseInt(date_s[firstDash+1:secondDash], 10, 32)
if err != nil {
return 0, ECGO_INVALID_DATETIME_FORMAT.addDetailln(err.Error()).throw()
}
month = int(i) - 1
i, err = strconv.ParseInt(date_s[secondDash+1:], 10, 32)
if err != nil {
return 0, ECGO_INVALID_DATETIME_FORMAT.addDetailln(err.Error()).throw()
}
day = int(i)
if !checkDate(year+1900, month+1, day) {
return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
}
} else {
return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
}
}
if time_s != "" {
firstColon = strings.Index(time_s, ":")
secondColon = strings.Index(time_s[firstColon+1:], ":")
if secondColon > 0 {
secondColon += firstColon + 1
}
period = strings.Index(time_s[secondColon+1:], ".")
if period > 0 {
period += secondColon + 1
}
if (firstColon > 0) && (secondColon > 0) && (secondColon < len(time_s)-1) {
i, err := strconv.ParseInt(time_s[:firstColon], 10, 32)
if err != nil {
return 0, ECGO_INVALID_DATETIME_FORMAT.addDetailln(err.Error()).throw()
}
hour = int(i)
i, err = strconv.ParseInt(time_s[firstColon+1:secondColon], 10, 32)
if err != nil {
return 0, ECGO_INVALID_DATETIME_FORMAT.addDetailln(err.Error()).throw()
}
minute = int(i)
if period > 0 && period < len(time_s)-1 {
i, err = strconv.ParseInt(time_s[secondColon+1:period], 10, 32)
if err != nil {
return 0, ECGO_INVALID_DATETIME_FORMAT.addDetailln(err.Error()).throw()
}
second = int(i)
nanos_s = time_s[period+1:]
if len(nanos_s) > NANOSECOND_DIGITS {
return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
}
if !unicode.IsDigit(rune(nanos_s[0])) {
return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
}
nanos_s = nanos_s + zeros[0:NANOSECOND_DIGITS-len(nanos_s)]
i, err = strconv.ParseInt(nanos_s, 10, 32)
if err != nil {
return 0, ECGO_INVALID_DATETIME_FORMAT.addDetailln(err.Error()).throw()
}
a_nanos = int(i)
} else if period > 0 {
return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
} else {
i, err = strconv.ParseInt(time_s[secondColon+1:], 10, 32)
if err != nil {
return 0, ECGO_INVALID_DATETIME_FORMAT.addDetailln(err.Error()).throw()
}
second = int(i)
}
if hour >= 24 || hour < 0 || minute >= 60 || minute < 0 || second >= 60 || second < 0 {
return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
}
} else {
return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
}
}
if tz_s != "" {
neg := false
if strings.Index(tz_s, "-") == 0 {
neg = true
}
if strings.Index(tz_s, "-") == 0 || strings.Index(tz_s, "+") == 0 {
tz_s = strings.TrimSpace(tz_s[1:])
}
hm := strings.Split(tz_s, ":")
var tzh, tzm int16 = 0, 0
switch len(hm) {
case 2:
s, err := strconv.ParseInt(strings.TrimSpace(hm[0]), 10, 16)
if err != nil {
return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
}
tzh = int16(s)
s, err = strconv.ParseInt(strings.TrimSpace(hm[1]), 10, 16)
if err != nil {
return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
}
tzm = int16(s)
case 1:
s, err := strconv.ParseInt(strings.TrimSpace(hm[0]), 10, 16)
if err != nil {
return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
}
tzh = int16(s)
default:
return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
}
ownTz = int(tzh*60 + tzm)
if ownTz < 0 {
return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
}
if neg {
ownTz *= -1
}
if ownTz <= -13*60 || ownTz > 14*60 {
return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
}
}
dt[OFFSET_YEAR] = year + 1900
dt[OFFSET_MONTH] = month + 1
if day == 0 {
dt[OFFSET_DAY] = 1
} else {
dt[OFFSET_DAY] = day
}
dt[OFFSET_HOUR] = hour
dt[OFFSET_MINUTE] = minute
dt[OFFSET_SECOND] = second
dt[OFFSET_NANOSECOND] = a_nanos
dt[OFFSET_TIMEZONE] = int(ownTz)
return dtype, nil
}
func transformTZ(dt []int, defaultSrcTz int, destTz int) {
srcTz := defaultSrcTz
if srcTz != INVALID_VALUE && destTz != INVALID_VALUE && destTz != srcTz {
dt = addMinute(dt, destTz-srcTz)
dt[OFFSET_TIMEZONE] = destTz
}
}
func encode(dt []int, column column, lTz int, dTz int) ([]byte, error) {
if dt[OFFSET_TIMEZONE] != INVALID_VALUE {
transformTZ(dt, dt[OFFSET_TIMEZONE], lTz)
}
if column.mask == MASK_LOCAL_DATETIME {
transformTZ(dt, dt[OFFSET_TIMEZONE], dTz)
}
if dt[OFFSET_YEAR] < -4712 || dt[OFFSET_YEAR] > 9999 {
return nil, ECGO_DATETIME_OVERFLOW.throw()
}
year := dt[OFFSET_YEAR]
month := dt[OFFSET_MONTH]
day := dt[OFFSET_DAY]
hour := dt[OFFSET_HOUR]
min := dt[OFFSET_MINUTE]
sec := dt[OFFSET_SECOND]
msec := dt[OFFSET_NANOSECOND]
var tz int
if dt[OFFSET_TIMEZONE] == INVALID_VALUE {
tz = dTz
} else {
tz = dt[OFFSET_TIMEZONE]
}
var ret []byte
if column.colType == DATE {
ret = make([]byte, 3)
ret[0] = (byte)(year & 0xFF)
if year >= 0 {
ret[1] = (byte)((year >> 8) | ((month & 0x01) << 7))
} else {
ret[1] = (byte)((year >> 8) & (((month & 0x01) << 7) | 0x7f))
}
ret[2] = (byte)(((month & 0x0E) >> 1) | (day << 3))
} else if column.colType == DATETIME {
msec /= 1000
ret = make([]byte, 8)
ret[0] = (byte)(year & 0xFF)
if year >= 0 {
ret[1] = (byte)((year >> 8) | ((month & 0x01) << 7))
} else {
ret[1] = (byte)((year >> 8) & (((month & 0x01) << 7) | 0x7f))
}
ret[2] = (byte)(((month & 0x0E) >> 1) | (day << 3))
ret[3] = (byte)(hour | ((min & 0x07) << 5))
ret[4] = (byte)(((min & 0x38) >> 3) | ((sec & 0x1F) << 3))
ret[5] = (byte)(((sec & 0x20) >> 5) | ((msec & 0x7F) << 1))
ret[6] = (byte)((msec >> 7) & 0xFF)
ret[7] = (byte)((msec >> 15) & 0xFF)
} else if column.colType == DATETIME2 {
ret = make([]byte, 9)
ret[0] = (byte)(year & 0xFF)
if year >= 0 {
ret[1] = (byte)((year >> 8) | ((month & 0x01) << 7))
} else {
ret[1] = (byte)((year >> 8) & (((month & 0x01) << 7) | 0x7f))
}
ret[2] = (byte)(((month & 0x0E) >> 1) | (day << 3))
ret[3] = (byte)(hour | ((min & 0x07) << 5))
ret[4] = (byte)(((min & 0x38) >> 3) | ((sec & 0x1F) << 3))
ret[5] = (byte)(((sec & 0x20) >> 5) | ((msec & 0x7F) << 1))
ret[6] = (byte)((msec >> 7) & 0xFF)
ret[7] = (byte)((msec >> 15) & 0xFF)
ret[8] = (byte)((msec >> 23) & 0xFF)
} else if column.colType == DATETIME_TZ {
msec /= 1000
ret = make([]byte, 10)
ret[0] = (byte)(year & 0xFF)
if year >= 0 {
ret[1] = (byte)((year >> 8) | ((month & 0x01) << 7))
} else {
ret[1] = (byte)((year >> 8) & (((month & 0x01) << 7) | 0x7f))
}
ret[2] = (byte)(((month & 0x0E) >> 1) | (day << 3))
ret[3] = (byte)(hour | ((min & 0x07) << 5))
ret[4] = (byte)(((min & 0x38) >> 3) | ((sec & 0x1F) << 3))
ret[5] = (byte)(((sec & 0x20) >> 5) | ((msec & 0x7F) << 1))
ret[6] = (byte)((msec >> 7) & 0xFF)
ret[7] = (byte)((msec >> 15) & 0xFF)
Dm_build_1346.Dm_build_1357(ret, 8, int16(tz))
} else if column.colType == DATETIME2_TZ {
ret = make([]byte, 11)
ret[0] = (byte)(year & 0xFF)
if year >= 0 {
ret[1] = (byte)((year >> 8) | ((month & 0x01) << 7))
} else {
ret[1] = (byte)((year >> 8) & (((month & 0x01) << 7) | 0x7f))
}
ret[2] = (byte)(((month & 0x0E) >> 1) | (day << 3))
ret[3] = (byte)(hour | ((min & 0x07) << 5))
ret[4] = (byte)(((min & 0x38) >> 3) | ((sec & 0x1F) << 3))
ret[5] = (byte)(((sec & 0x20) >> 5) | ((msec & 0x7F) << 1))
ret[6] = (byte)((msec >> 7) & 0xFF)
ret[7] = (byte)((msec >> 15) & 0xFF)
ret[8] = (byte)((msec >> 23) & 0xFF)
Dm_build_1346.Dm_build_1357(ret, 8, int16(tz))
} else if column.colType == TIME {
msec /= 1000
ret = make([]byte, 5)
ret[0] = (byte)(hour | ((min & 0x07) << 5))
ret[1] = (byte)(((min & 0x38) >> 3) | ((sec & 0x1F) << 3))
ret[2] = (byte)(((sec & 0x20) >> 5) | ((msec & 0x7F) << 1))
ret[3] = (byte)((msec >> 7) & 0xFF)
ret[4] = (byte)((msec >> 15) & 0xFF)
} else if column.colType == TIME_TZ {
msec /= 1000
ret = make([]byte, 7)
ret[0] = (byte)(hour | ((min & 0x07) << 5))
ret[1] = (byte)(((min & 0x38) >> 3) | ((sec & 0x1F) << 3))
ret[2] = (byte)(((sec & 0x20) >> 5) | ((msec & 0x7F) << 1))
ret[3] = (byte)((msec >> 7) & 0xFF)
ret[4] = (byte)((msec >> 15) & 0xFF)
Dm_build_1346.Dm_build_1357(ret, 5, int16(tz))
}
return ret, nil
}
func toDate(x int64, column column, conn DmConnection) ([]byte, error) {
switch column.colType {
case DATETIME, DATETIME2:
if x > 2958463*24*60*60 {
return nil, ECGO_DATETIME_OVERFLOW.throw()
}
dt := toDTFromUnix(x-Seconds_1900_1970, 0)
return encode(dt, column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
case TIME:
dt := toDTFromUnix(x, 0)
return encode(dt, column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
case DATE:
if x > 2958463 {
return nil, ECGO_DATETIME_OVERFLOW.throw()
}
dt := toDTFromUnix(x*24*60*60-Seconds_1900_1970, 0)
if dt[OFFSET_YEAR] < -4712 || dt[OFFSET_YEAR] > 9999 {
return nil, ECGO_DATETIME_OVERFLOW.throw()
}
return encode(dt, column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
default:
return nil, ECGO_DATA_CONVERTION_ERROR.throw()
}
}
func checkDate(year int, month int, day int) bool {
if year > 9999 || year < -4712 || month > 12 || month < 1 {
return false
}
monthDays := getDaysOfMonth(year, month)
if day > monthDays || day < 1 {
return false
}
return true
}
func getDaysOfMonth(year int, month int) int {
switch month {
case 1, 3, 5, 7, 8, 10, 12:
return 31
case 4, 6, 9, 11:
return 30
case 2:
if isLeapYear(year) {
return 29
}
return 28
default:
return 0
}
}
func isLeapYear(year int) bool {
return (year%4 == 0 && year%100 != 0) || year%400 == 0
}
func addYear(dt []int, n int) []int {
dt[OFFSET_YEAR] += n
return dt
}
func addMonth(dt []int, n int) []int {
month := dt[OFFSET_MONTH] + n
addYearValue := month / 12
if month %= 12; month < 1 {
month += 12
addYearValue--
}
daysOfMonth := getDaysOfMonth(dt[OFFSET_YEAR], month)
if dt[OFFSET_DAY] > daysOfMonth {
dt[OFFSET_DAY] = daysOfMonth
}
dt[OFFSET_MONTH] = month
addYear(dt, addYearValue)
return dt
}
func addDay(dt []int, n int) []int {
tmp := dt[OFFSET_DAY] + n
monthDays := 0
monthDays = getDaysOfMonth(dt[OFFSET_YEAR], dt[OFFSET_MONTH])
for tmp > monthDays || tmp <= 0 {
if tmp > monthDays {
addMonth(dt, 1)
tmp -= monthDays
} else {
addMonth(dt, -1)
tmp += monthDays
}
}
dt[OFFSET_DAY] = tmp
return dt
}
func addHour(dt []int, n int) []int {
hour := dt[OFFSET_HOUR] + n
addDayValue := hour / 24
if hour %= 24; hour < 0 {
hour += 24
addDayValue--
}
dt[OFFSET_HOUR] = hour
addDay(dt, addDayValue)
return dt
}
func addMinute(dt []int, n int) []int {
minute := dt[OFFSET_MINUTE] + n
addHourValue := minute / 60
if minute %= 60; minute < 0 {
minute += 60
addHourValue--
}
dt[OFFSET_MINUTE] = minute
addHour(dt, addHourValue)
return dt
}
+917
View File
@@ -0,0 +1,917 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"strconv"
"time"
"gitee.com/chunanyong/dm/util"
)
var DB2G db2g
type db2g struct {
}
func (DB2G db2g) processVarchar2(bytes []byte, prec int) []byte {
rbytes := make([]byte, prec)
copy(rbytes[:len(bytes)], bytes[:])
for i := len(bytes); i < len(rbytes); i++ {
rbytes[i] = ' '
}
return rbytes
}
func (DB2G db2g) charToString(bytes []byte, column *column, conn *DmConnection) string {
if column.colType == VARCHAR2 {
bytes = DB2G.processVarchar2(bytes, int(column.prec))
} else if column.colType == CLOB {
clob := newClobFromDB(bytes, conn, column, true)
clobLen, _ := clob.GetLength()
clobStr, _ := clob.getSubString(1, int32(clobLen))
return clobStr
}
return Dm_build_1346.Dm_build_1598(bytes, conn.serverEncoding, conn)
}
func (DB2G db2g) charToFloat64(bytes []byte, column *column, conn *DmConnection) (float64, error) {
str := DB2G.charToString(bytes, column, conn)
val, err := strconv.ParseFloat(str, 64)
if err != nil {
return 0, ECGO_DATA_CONVERTION_ERROR.throw()
}
return val, nil
}
func (DB2G db2g) charToDeciaml(bytes []byte, column *column, conn *DmConnection) (*DmDecimal, error) {
str := DB2G.charToString(bytes, column, conn)
return NewDecimalFromString(str)
}
func (DB2G db2g) BinaryToInt64(bytes []byte, column *column, conn *DmConnection) (int64, error) {
if column.colType == BLOB {
blob := newBlobFromDB(bytes, conn, column, true)
blobLen, err := blob.GetLength()
if err != nil {
return 0, err
}
bytes, err = blob.getBytes(1, int32(blobLen))
if err != nil {
return 0, err
}
}
var n, b int64 = 0, 0
startIndex := 0
var length int
if len(bytes) > 8 {
length = 8
for j := 0; j < len(bytes)-8; j++ {
if bytes[j] != 0 {
return 0, ECGO_DATA_CONVERTION_ERROR.throw()
}
startIndex = len(bytes) - 8
length = 8
}
} else {
length = len(bytes)
}
for j := startIndex; j < startIndex+length; j++ {
b = int64(0xff & bytes[j])
n = b | (n << 8)
}
return n, nil
}
func (DB2G db2g) decToDecimal(bytes []byte, prec int, scale int, compatibleOracle bool) (*DmDecimal, error) {
if compatibleOracle {
prec = -1
scale = -1
}
return newDecimal(bytes, prec, scale)
}
func (DB2G db2g) toBytes(bytes []byte, column *column, conn *DmConnection) ([]byte, error) {
retBytes := Dm_build_1346.Dm_build_1497(bytes, 0, len(bytes))
switch column.colType {
case CLOB:
clob := newClobFromDB(retBytes, conn, column, true)
str, err := clob.getSubString(1, int32(clob.length))
if err != nil {
return nil, err
}
return Dm_build_1346.Dm_build_1562(str, conn.getServerEncoding(), conn), nil
case BLOB:
blob := newBlobFromDB(retBytes, conn, column, true)
bs, err := blob.getBytes(1, int32(blob.length))
if err != nil {
return nil, err
}
return bs, nil
}
return nil, ECGO_DATA_CONVERTION_ERROR.throw()
}
func (DB2G db2g) toString(bytes []byte, column *column, conn *DmConnection) string {
switch column.colType {
case CHAR, VARCHAR, VARCHAR2:
return DB2G.charToString(bytes, column, conn)
case BIT, BOOLEAN, TINYINT:
return strconv.FormatInt(int64(bytes[0]), 10)
case SMALLINT:
return strconv.FormatInt(int64(Dm_build_1346.Dm_build_1570(bytes)), 10)
case INT:
return strconv.FormatInt(int64(Dm_build_1346.Dm_build_1573(bytes)), 10)
case BIGINT:
return strconv.FormatInt(int64(Dm_build_1346.Dm_build_1576(bytes)), 10)
case REAL:
return strconv.FormatFloat(float64(Dm_build_1346.Dm_build_1579(bytes)), 'f', -1, 32)
case DOUBLE:
return strconv.FormatFloat(float64(Dm_build_1346.Dm_build_1582(bytes)), 'f', -1, 64)
case DECIMAL:
case BINARY, VARBINARY:
util.StringUtil.BytesToHexString(bytes, false)
case BLOB:
case CLOB:
case DATE:
dt := decode(bytes, column.isBdta, *column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
if conn.FormatDate != "" {
return dtToStringByOracleFormat(dt, conn.FormatDate, column.scale, int(conn.OracleDateLanguage))
}
case TIME:
dt := decode(bytes, column.isBdta, *column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
if conn.FormatTime != "" {
return dtToStringByOracleFormat(dt, conn.FormatTime, column.scale, int(conn.OracleDateLanguage))
}
case DATETIME, DATETIME2:
dt := decode(bytes, column.isBdta, *column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
if conn.FormatTimestamp != "" {
return dtToStringByOracleFormat(dt, conn.FormatTimestamp, column.scale, int(conn.OracleDateLanguage))
}
case TIME_TZ:
dt := decode(bytes, column.isBdta, *column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
if conn.FormatTimeTZ != "" {
return dtToStringByOracleFormat(dt, conn.FormatTimeTZ, column.scale, int(conn.OracleDateLanguage))
}
case DATETIME_TZ, DATETIME2_TZ:
dt := decode(bytes, column.isBdta, *column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
if conn.FormatTimestampTZ != "" {
return dtToStringByOracleFormat(dt, conn.FormatTimestampTZ, column.scale, int(conn.OracleDateLanguage))
}
case INTERVAL_DT:
return newDmIntervalDTByBytes(bytes).String()
case INTERVAL_YM:
return newDmIntervalYMByBytes(bytes).String()
case ARRAY:
case SARRAY:
case CLASS:
case PLTYPE_RECORD:
}
return ""
}
func (DB2G db2g) toBool(bytes []byte, column *column, conn *DmConnection) (bool, error) {
switch column.colType {
case BIT, BOOLEAN, TINYINT:
return bytes[0] != 0, nil
case SMALLINT:
return Dm_build_1346.Dm_build_1443(bytes, 0) != 0, nil
case INT:
return Dm_build_1346.Dm_build_1448(bytes, 0) != 0, nil
case BIGINT:
return Dm_build_1346.Dm_build_1453(bytes, 0) != 0, nil
case REAL:
return Dm_build_1346.Dm_build_1458(bytes, 0) != 0, nil
case DOUBLE:
return Dm_build_1346.Dm_build_1462(bytes, 0) != 0, nil
case DECIMAL:
case CHAR, VARCHAR, VARCHAR2, CLOB:
return G2DB.toBool(DB2G.charToString(bytes, column, conn))
}
return false, ECGO_DATA_CONVERTION_ERROR.throw()
}
func (DB2G db2g) toByte(bytes []byte, column *column, conn *DmConnection) (byte, error) {
switch column.colType {
case BIT, BOOLEAN, TINYINT:
if bytes == nil || len(bytes) == 0 {
return 0, nil
} else {
return bytes[0], nil
}
case SMALLINT:
tval := Dm_build_1346.Dm_build_1443(bytes, 0)
if tval < int16(BYTE_MIN) || tval > int16(BYTE_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return byte(tval), nil
case INT:
tval := Dm_build_1346.Dm_build_1448(bytes, 0)
if tval < int32(BYTE_MIN) || tval > int32(BYTE_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return byte(tval), nil
case BIGINT:
tval := Dm_build_1346.Dm_build_1453(bytes, 0)
if tval < int64(BYTE_MIN) || tval > int64(BYTE_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return byte(tval), nil
case REAL:
tval := Dm_build_1346.Dm_build_1458(bytes, 0)
if tval < float32(BYTE_MIN) || tval > float32(BYTE_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return byte(tval), nil
case DOUBLE:
tval := Dm_build_1346.Dm_build_1462(bytes, 0)
if tval < float64(BYTE_MIN) || tval > float64(BYTE_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return byte(tval), nil
case DECIMAL:
case CHAR, VARCHAR, VARCHAR2, CLOB:
tval, err := DB2G.charToFloat64(bytes, column, conn)
if err != nil {
return 0, err
}
if tval < float64(BYTE_MIN) || tval > float64(BYTE_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return byte(tval), nil
case BINARY, VARBINARY, BLOB:
{
tval, err := DB2G.BinaryToInt64(bytes, column, conn)
if err != nil {
return 0, err
}
if tval < int64(BYTE_MIN) || tval > int64(BYTE_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return byte(tval), nil
}
}
return 0, ECGO_DATA_CONVERTION_ERROR.throw()
}
func (DB2G db2g) toInt8(bytes []byte, column *column, conn *DmConnection) (int8, error) {
switch column.colType {
case BIT, BOOLEAN, TINYINT:
if bytes == nil || len(bytes) == 0 {
return 0, nil
}
return int8(bytes[0]), nil
case SMALLINT:
tval := Dm_build_1346.Dm_build_1443(bytes, 0)
if tval < int16(INT8_MIN) || tval < int16(INT8_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return int8(tval), nil
case INT:
tval := Dm_build_1346.Dm_build_1448(bytes, 0)
if tval < int32(INT8_MIN) || tval > int32(INT8_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return int8(tval), nil
case BIGINT:
tval := Dm_build_1346.Dm_build_1453(bytes, 0)
if tval < int64(INT8_MIN) || tval > int64(INT8_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return int8(tval), nil
case REAL:
tval := Dm_build_1346.Dm_build_1458(bytes, 0)
if tval < float32(INT8_MIN) || tval > float32(INT8_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return int8(tval), nil
case DOUBLE:
tval := Dm_build_1346.Dm_build_1462(bytes, 0)
if tval < float64(INT8_MIN) || tval > float64(INT8_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return int8(tval), nil
case DECIMAL:
case CHAR, VARCHAR, VARCHAR2, CLOB:
tval, err := DB2G.charToFloat64(bytes, column, conn)
if err != nil {
return 0, err
}
if tval < float64(INT8_MIN) || tval > float64(INT8_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return int8(tval), nil
case BINARY, VARBINARY, BLOB:
{
tval, err := DB2G.BinaryToInt64(bytes, column, conn)
if err != nil {
return 0, err
}
if tval < int64(INT8_MIN) || tval > int64(INT8_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return int8(tval), nil
}
}
return 0, ECGO_DATA_CONVERTION_ERROR.throw()
}
func (DB2G db2g) toInt16(bytes []byte, column *column, conn *DmConnection) (int16, error) {
switch column.colType {
case BIT, BOOLEAN, TINYINT:
if bytes == nil || len(bytes) == 0 {
return 0, nil
}
return int16(bytes[0]), nil
case SMALLINT:
return Dm_build_1346.Dm_build_1443(bytes, 0), nil
case INT:
tval := Dm_build_1346.Dm_build_1448(bytes, 0)
if tval < int32(INT16_MIN) || tval > int32(INT16_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return int16(tval), nil
case BIGINT:
tval := Dm_build_1346.Dm_build_1453(bytes, 0)
if tval < int64(INT16_MIN) || tval > int64(INT16_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return int16(tval), nil
case REAL:
tval := Dm_build_1346.Dm_build_1458(bytes, 0)
if tval < float32(INT16_MIN) || tval > float32(INT16_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return int16(tval), nil
case DOUBLE:
tval := Dm_build_1346.Dm_build_1462(bytes, 0)
if tval < float64(INT16_MIN) || tval > float64(INT16_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return int16(tval), nil
case DECIMAL:
case CHAR, VARCHAR, VARCHAR2, CLOB:
tval, err := DB2G.charToFloat64(bytes, column, conn)
if err != nil {
return 0, err
}
if tval < float64(INT16_MIN) || tval > float64(INT16_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return int16(tval), nil
case BINARY, VARBINARY, BLOB:
{
tval, err := DB2G.BinaryToInt64(bytes, column, conn)
if err != nil {
return 0, err
}
if tval < int64(INT16_MIN) || tval > int64(INT16_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return int16(tval), nil
}
}
return 0, ECGO_DATA_CONVERTION_ERROR.throw()
}
func (DB2G db2g) toUInt16(bytes []byte, column *column, conn *DmConnection) (uint16, error) {
switch column.colType {
case BIT, BOOLEAN, TINYINT:
if bytes == nil || len(bytes) == 0 {
return 0, nil
}
return uint16(bytes[0]), nil
case SMALLINT:
return uint16(Dm_build_1346.Dm_build_1443(bytes, 0)), nil
case INT:
tval := Dm_build_1346.Dm_build_1448(bytes, 0)
if tval < int32(UINT16_MIN) || tval > int32(UINT16_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return uint16(tval), nil
case BIGINT:
tval := Dm_build_1346.Dm_build_1453(bytes, 0)
if tval < int64(UINT16_MIN) || tval > int64(UINT16_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return uint16(tval), nil
case REAL:
tval := Dm_build_1346.Dm_build_1458(bytes, 0)
if tval < float32(UINT16_MIN) || tval > float32(UINT16_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return uint16(tval), nil
case DOUBLE:
tval := Dm_build_1346.Dm_build_1462(bytes, 0)
if tval < float64(UINT16_MIN) || tval > float64(UINT16_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return uint16(tval), nil
case DECIMAL:
case CHAR, VARCHAR, VARCHAR2, CLOB:
tval, err := DB2G.charToFloat64(bytes, column, conn)
if err != nil {
return 0, err
}
if tval < float64(UINT16_MIN) || tval > float64(UINT16_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return uint16(tval), nil
case BINARY, VARBINARY, BLOB:
{
tval, err := DB2G.BinaryToInt64(bytes, column, conn)
if err != nil {
return 0, err
}
if tval < int64(UINT16_MIN) || tval > int64(UINT16_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return uint16(tval), nil
}
}
return 0, ECGO_DATA_CONVERTION_ERROR.throw()
}
func (DB2G db2g) toInt32(bytes []byte, column *column, conn *DmConnection) (int32, error) {
switch column.colType {
case BIT, BOOLEAN, TINYINT:
if bytes == nil || len(bytes) == 0 {
return 0, nil
}
return int32(bytes[0]), nil
case SMALLINT:
return int32(Dm_build_1346.Dm_build_1443(bytes, 0)), nil
case INT:
return Dm_build_1346.Dm_build_1448(bytes, 0), nil
case BIGINT:
tval := Dm_build_1346.Dm_build_1453(bytes, 0)
if tval < int64(INT32_MIN) || tval > int64(INT32_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return int32(tval), nil
case REAL:
tval := Dm_build_1346.Dm_build_1458(bytes, 0)
if tval < float32(INT32_MIN) || tval > float32(INT32_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return int32(tval), nil
case DOUBLE:
tval := Dm_build_1346.Dm_build_1462(bytes, 0)
if tval < float64(INT32_MIN) || tval > float64(INT32_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return int32(tval), nil
case DECIMAL:
case CHAR, VARCHAR, VARCHAR2, CLOB:
tval, err := DB2G.charToFloat64(bytes, column, conn)
if err != nil {
return 0, err
}
if tval < float64(INT32_MIN) || tval > float64(INT32_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return int32(tval), nil
case BINARY, VARBINARY, BLOB:
{
tval, err := DB2G.BinaryToInt64(bytes, column, conn)
if err != nil {
return 0, err
}
if tval < int64(INT32_MIN) || tval > int64(INT32_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return int32(tval), nil
}
}
return 0, ECGO_DATA_CONVERTION_ERROR.throw()
}
func (DB2G db2g) toUInt32(bytes []byte, column *column, conn *DmConnection) (uint32, error) {
switch column.colType {
case BIT, BOOLEAN, TINYINT:
if bytes == nil || len(bytes) == 0 {
return 0, nil
}
return uint32(bytes[0]), nil
case SMALLINT:
return uint32(Dm_build_1346.Dm_build_1443(bytes, 0)), nil
case INT:
return uint32(Dm_build_1346.Dm_build_1448(bytes, 0)), nil
case BIGINT:
tval := Dm_build_1346.Dm_build_1453(bytes, 0)
if tval < int64(UINT32_MIN) || tval > int64(UINT32_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return uint32(tval), nil
case REAL:
tval := Dm_build_1346.Dm_build_1458(bytes, 0)
if tval < float32(UINT32_MIN) || tval > float32(UINT32_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return uint32(tval), nil
case DOUBLE:
tval := Dm_build_1346.Dm_build_1462(bytes, 0)
if tval < float64(UINT32_MIN) || tval > float64(UINT32_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return uint32(tval), nil
case DECIMAL:
case CHAR, VARCHAR, VARCHAR2, CLOB:
tval, err := DB2G.charToFloat64(bytes, column, conn)
if err != nil {
return 0, err
}
if tval < float64(UINT32_MIN) || tval > float64(UINT32_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return uint32(tval), nil
case BINARY, VARBINARY, BLOB:
{
tval, err := DB2G.BinaryToInt64(bytes, column, conn)
if err != nil {
return 0, err
}
if tval < int64(UINT32_MIN) || tval > int64(UINT32_MAX) {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return uint32(tval), nil
}
}
return 0, ECGO_DATA_CONVERTION_ERROR.throw()
}
func (DB2G db2g) toInt64(bytes []byte, column *column, conn *DmConnection) (int64, error) {
switch column.colType {
case BOOLEAN, BIT, TINYINT:
if bytes == nil || len(bytes) == 0 {
return int64(0), nil
} else {
return int64(bytes[0]), nil
}
case SMALLINT:
return int64(Dm_build_1346.Dm_build_1570(bytes)), nil
case INT:
return int64(Dm_build_1346.Dm_build_1573(bytes)), nil
case BIGINT:
return int64(Dm_build_1346.Dm_build_1576(bytes)), nil
case REAL:
return int64(Dm_build_1346.Dm_build_1579(bytes)), nil
case DOUBLE:
return int64(Dm_build_1346.Dm_build_1582(bytes)), nil
case CHAR, VARCHAR2, VARCHAR, CLOB:
tval, err := DB2G.charToFloat64(bytes, column, conn)
if err != nil {
return 0, err
}
if int64(tval) < INT64_MIN || int64(tval) > INT64_MAX {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return int64(tval), nil
case BINARY, VARBINARY, BLOB:
tval, err := DB2G.BinaryToInt64(bytes, column, conn)
if err != nil {
return 0, err
}
return tval, nil
}
return 0, ECGO_DATA_CONVERTION_ERROR.throw()
}
func (DB2G db2g) toUInt64(bytes []byte, column *column, conn *DmConnection) (uint64, error) {
switch column.colType {
case BOOLEAN, BIT, TINYINT:
if bytes == nil || len(bytes) == 0 {
return uint64(0), nil
} else {
return uint64(bytes[0]), nil
}
case SMALLINT:
return uint64(Dm_build_1346.Dm_build_1570(bytes)), nil
case INT:
return uint64(Dm_build_1346.Dm_build_1573(bytes)), nil
case BIGINT:
return uint64(Dm_build_1346.Dm_build_1576(bytes)), nil
case REAL:
return uint64(Dm_build_1346.Dm_build_1579(bytes)), nil
case DOUBLE:
return uint64(Dm_build_1346.Dm_build_1582(bytes)), nil
case CHAR, VARCHAR2, VARCHAR, CLOB:
tval, err := DB2G.charToFloat64(bytes, column, conn)
if err != nil {
return 0, err
}
if uint64(tval) < UINT64_MIN || uint64(tval) > UINT64_MAX {
return 0, ECGO_DATA_OVERFLOW.throw()
}
return uint64(tval), nil
case BINARY, VARBINARY, BLOB:
tval, err := DB2G.BinaryToInt64(bytes, column, conn)
if err != nil {
return 0, err
}
return uint64(tval), nil
}
return 0, ECGO_DATA_CONVERTION_ERROR.throw()
}
func (DB2G db2g) toInt(bytes []byte, column *column, conn *DmConnection) (int, error) {
if strconv.IntSize == 32 {
tmp, err := DB2G.toInt32(bytes, column, conn)
return int(tmp), err
} else {
tmp, err := DB2G.toInt64(bytes, column, conn)
return int(tmp), err
}
}
func (DB2G db2g) toUInt(bytes []byte, column *column, conn *DmConnection) (uint, error) {
if strconv.IntSize == 32 {
tmp, err := DB2G.toUInt32(bytes, column, conn)
return uint(tmp), err
} else {
tmp, err := DB2G.toUInt64(bytes, column, conn)
return uint(tmp), err
}
}
func (DB2G db2g) toFloat32(bytes []byte, column *column, conn *DmConnection) (float32, error) {
switch column.colType {
case BIT, BOOLEAN, TINYINT:
if bytes == nil || len(bytes) == 0 {
return 0, nil
}
return float32(bytes[0]), nil
case SMALLINT:
return float32(Dm_build_1346.Dm_build_1443(bytes, 0)), nil
case INT:
return float32(Dm_build_1346.Dm_build_1448(bytes, 0)), nil
case BIGINT:
return float32(Dm_build_1346.Dm_build_1453(bytes, 0)), nil
case REAL:
return Dm_build_1346.Dm_build_1458(bytes, 0), nil
case DOUBLE:
dval := Dm_build_1346.Dm_build_1462(bytes, 0)
return float32(dval), nil
case DECIMAL:
dval, err := DB2G.decToDecimal(bytes, int(column.prec), int(column.scale), conn.CompatibleOracle())
if err != nil {
return 0, err
}
return float32(dval.ToFloat64()), nil
case CHAR, VARCHAR2, VARCHAR, CLOB:
dval, err := DB2G.charToDeciaml(bytes, column, conn)
if err != nil {
return 0, err
}
return float32(dval.ToFloat64()), nil
}
return 0, ECGO_DATA_CONVERTION_ERROR.throw()
}
func (DB2G db2g) toFloat64(bytes []byte, column *column, conn *DmConnection) (float64, error) {
switch column.colType {
case BIT, BOOLEAN, TINYINT:
if bytes == nil || len(bytes) == 0 {
return 0, nil
}
return float64(bytes[0]), nil
case SMALLINT:
return float64(Dm_build_1346.Dm_build_1443(bytes, 0)), nil
case INT:
return float64(Dm_build_1346.Dm_build_1448(bytes, 0)), nil
case BIGINT:
return float64(Dm_build_1346.Dm_build_1453(bytes, 0)), nil
case REAL:
return float64(Dm_build_1346.Dm_build_1458(bytes, 0)), nil
case DOUBLE:
return Dm_build_1346.Dm_build_1462(bytes, 0), nil
case DECIMAL:
dval, err := DB2G.decToDecimal(bytes, int(column.prec), int(column.scale), conn.CompatibleOracle())
if err != nil {
return 0, err
}
return dval.ToFloat64(), nil
case CHAR, VARCHAR2, VARCHAR, CLOB:
dval, err := DB2G.charToDeciaml(bytes, column, conn)
if err != nil {
return 0, err
}
return dval.ToFloat64(), nil
}
return 0, ECGO_DATA_CONVERTION_ERROR.throw()
}
func (DB2G db2g) toDmBlob(value []byte, column *column, conn *DmConnection) *DmBlob {
switch column.colType {
case BLOB:
return newBlobFromDB(value, conn, column, conn.lobFetchAll())
default:
return newBlobOfLocal(value, conn)
}
}
func (DB2G db2g) toDmClob(value []byte, conn *DmConnection, column *column) *DmClob {
switch column.colType {
case CLOB:
return newClobFromDB(value, conn, column, conn.lobFetchAll())
default:
return newClobOfLocal(DB2G.toString(value, column, conn), conn)
}
}
func (DB2G db2g) toDmDecimal(value []byte, column *column, conn *DmConnection) (*DmDecimal, error) {
switch column.colType {
case BIT, BOOLEAN, TINYINT:
if value == nil || len(value) == 0 {
return NewDecimalFromInt64(0)
} else {
return NewDecimalFromInt64(int64(value[0]))
}
case SMALLINT:
return NewDecimalFromInt64(int64(Dm_build_1346.Dm_build_1443(value, 0)))
case INT:
return NewDecimalFromInt64(int64(Dm_build_1346.Dm_build_1448(value, 0)))
case BIGINT:
return NewDecimalFromInt64(Dm_build_1346.Dm_build_1453(value, 0))
case REAL:
return NewDecimalFromFloat64(float64(Dm_build_1346.Dm_build_1458(value, 0)))
case DOUBLE:
return NewDecimalFromFloat64(Dm_build_1346.Dm_build_1462(value, 0))
case DECIMAL:
return decodeDecimal(value, int(column.prec), int(column.scale))
case CHAR, VARCHAR, VARCHAR2, CLOB:
return DB2G.charToDeciaml(value, column, conn)
}
return nil, ECGO_DATA_CONVERTION_ERROR
}
func (DB2G db2g) toTime(bytes []byte, column *column, conn *DmConnection) (time.Time, error) {
switch column.colType {
case DATE, TIME, TIME_TZ, DATETIME_TZ, DATETIME, DATETIME2_TZ, DATETIME2:
dt := decode(bytes, column.isBdta, *column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
return toTimeFromDT(dt, int(conn.dmConnector.localTimezone)), nil
case CHAR, VARCHAR2, VARCHAR, CLOB:
return toTimeFromString(DB2G.charToString(bytes, column, conn), int(conn.dmConnector.localTimezone)), nil
}
return time.Now(), ECGO_DATA_CONVERTION_ERROR.throw()
}
func (DB2G db2g) toObject(bytes []byte, column *column, conn *DmConnection) (interface{}, error) {
switch column.colType {
case BIT, BOOLEAN:
return bytes[0] != 0, nil
case TINYINT:
return Dm_build_1346.Dm_build_1439(bytes, 0), nil
case SMALLINT:
return Dm_build_1346.Dm_build_1443(bytes, 0), nil
case INT:
return Dm_build_1346.Dm_build_1448(bytes, 0), nil
case BIGINT:
return Dm_build_1346.Dm_build_1453(bytes, 0), nil
case DECIMAL:
return DB2G.decToDecimal(bytes, int(column.prec), int(column.scale), conn.CompatibleOracle())
case REAL:
return Dm_build_1346.Dm_build_1458(bytes, 0), nil
case DOUBLE:
return Dm_build_1346.Dm_build_1462(bytes, 0), nil
case DATE, TIME, DATETIME, TIME_TZ, DATETIME_TZ, DATETIME2, DATETIME2_TZ:
dt := decode(bytes, column.isBdta, *column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
return toTimeFromDT(dt, int(conn.dmConnector.localTimezone)), nil
case BINARY, VARBINARY:
return bytes, nil
case BLOB:
blob := newBlobFromDB(bytes, conn, column, conn.lobFetchAll())
if util.StringUtil.EqualsIgnoreCase(column.typeName, "LONGVARBINARY") {
l, err := blob.GetLength()
if err != nil {
return nil, err
}
return blob.getBytes(1, int32(l))
} else {
return blob, nil
}
case CHAR, VARCHAR, VARCHAR2:
val := DB2G.charToString(bytes, column, conn)
if column.mask == MASK_BFILE {
}
return val, nil
case CLOB:
clob := newClobFromDB(bytes, conn, column, conn.lobFetchAll())
if util.StringUtil.EqualsIgnoreCase(column.typeName, "LONGVARCHAR") {
l, err := clob.GetLength()
if err != nil {
return nil, err
}
return clob.getSubString(1, int32(l))
} else {
return clob, nil
}
case INTERVAL_YM:
return newDmIntervalYMByBytes(bytes), nil
case INTERVAL_DT:
return newDmIntervalDTByBytes(bytes), nil
case ARRAY:
return TypeDataSV.bytesToArray(bytes, nil, column.typeDescriptor)
case SARRAY:
return TypeDataSV.bytesToSArray(bytes, nil, column.typeDescriptor)
case CLASS:
case PLTYPE_RECORD:
default:
return nil, ECGO_DATA_CONVERTION_ERROR.throw()
}
return nil, ECGO_DATA_CONVERTION_ERROR.throw()
}
func (DB2G db2g) toComplexType(bytes []byte, column *column, conn *DmConnection) (interface{}, error) {
switch column.colType {
case BLOB:
if !isComplexType(int(column.colType), int(column.scale)) {
return nil, ECGO_DATA_CONVERTION_ERROR.throw()
}
blob := newBlobFromDB(bytes, conn, column, true)
return TypeDataSV.objBlobToObj(blob, column.typeDescriptor)
case ARRAY:
return TypeDataSV.bytesToArray(bytes, nil, column.typeDescriptor)
case SARRAY:
return TypeDataSV.bytesToSArray(bytes, nil, column.typeDescriptor)
case CLASS:
return TypeDataSV.bytesToObj(bytes, nil, column.typeDescriptor)
case PLTYPE_RECORD:
return nil, ECGO_DATA_CONVERTION_ERROR.throw()
default:
return nil, ECGO_DATA_CONVERTION_ERROR.throw()
}
}
+48
View File
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package i18n
import (
"encoding/json"
"golang.org/x/text/language"
"golang.org/x/text/message"
)
type msg struct {
Id string `json:"id"`
Translation string `json:"translation,omitempty"`
}
type i18n struct {
Language string `json:"language"`
Messages []msg `json:"messages"`
}
func InitConfig(jsonStr string) {
var i18n i18n
json.Unmarshal([]byte(jsonStr), &i18n)
msaArry := i18n.Messages
tag := language.MustParse(i18n.Language)
for _, e := range msaArry {
message.SetString(tag, e.Id, e.Translation)
}
}
func Get(key string, locale int) string {
var p *message.Printer
switch locale {
case 0:
p = message.NewPrinter(language.SimplifiedChinese)
case 1:
p = message.NewPrinter(language.AmericanEnglish)
case 2:
p = message.NewPrinter(language.TraditionalChinese)
}
return p.Sprintf(key)
}
+248
View File
@@ -0,0 +1,248 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package i18n
const Messages_en_US = `{
"language": "en-US",
"messages": [
{
"id": "error.dsn.invalidSchema",
"translation": "DSN must start with dm://"
},
{
"id": "error.dsn.invalidFormat",
"translation": "DSN is invalid"
},
{
"id": "error.unsupported.scan",
"translation": "Unsupported scan type"
},
{
"id": "error.invalidParameterNumber",
"translation": "Invalid parameter number"
},
{
"id": "error.initThirdPartCipherFailed",
"translation": "Init third part cipher failed"
},
{
"id": "error.connectionSwitchFailed",
"translation": "Connection switch failed"
},
{
"id": "error.connectionSwitched",
"translation": "Connection has been switched"
},
{
"id": "error.invalidServerMode",
"translation": "Invalid server mode"
},
{
"id": "error.osauthError",
"translation": "At the same time using the specifed user login and OS authentication login, please determine a way."
},
{
"id": "error.notQuerySQL",
"translation": "The SQL is not a query SQL"
},
{
"id": "error.notExecSQL",
"translation": "The SQL is not a execute SQL"
},
{
"id": "error.invalidTranIsolation",
"translation": "invalid Transaltion Isolation"
},
{
"id": "errorCommitInAutoCommitMode",
"translation": "Can't commit in Auto commit status"
},
{
"id": "errorCommitInAutoCommitMode",
"translation": "Can't rollback in Auto commit status"
},
{
"id": "errorStatementHandleClosed",
"translation": "Statement handle is closed"
},
{
"id": "errorResultSetColsed",
"translation": "Resultset is closed"
},
{
"id": "error.communicationError",
"translation": "Communication error"
},
{
"id": "error.msgCheckError",
"translation": "Message check error"
},
{
"id": "error.unkownNetWork",
"translation": "Unkown net work"
},
{
"id": "error.serverVersion",
"translation": "Server version is too low"
},
{
"id": "error.usernameTooLong",
"translation": "Username is too long."
},
{
"id": "error.passwordTooLong",
"translation": "Password to login is too long."
},
{
"id": "error.dataTooLong",
"translation": "The data is too large to support."
},
{
"id": "error.invalidColumnType",
"translation": "Invalid column type"
},
{
"id": "error.dataConvertionError",
"translation": "Data convertion error"
},
{
"id": "error.invalidConn",
"translation": "Invalid connection"
},
{
"id": "error.invalidHex",
"translation": "Invalid Hex Number."
},
{
"id": "error.invalidBFile",
"translation": "Invalid BFile format string."
},
{
"id": "error.dataOverflow",
"translation": "Digital overflow"
},
{
"id": "error.invalidDateTimeFormat",
"translation": "Invalid datetime type format"
},
{
"id": "error.datetimeOverflow",
"translation": "Digital overflow"
},
{
"id": "error.invalidTimeInterval",
"translation": "Invalid time interval type value"
},
{
"id": "error.unsupportedInparamType",
"translation": "Unsupported input parameter type"
},
{
"id": "error.unsupportedOutparamType",
"translation": "Unsupported output parameter type"
},
{
"id": "error.unsupportedType",
"translation": "Not support this type"
},
{
"id": "error.invalidObjBlob",
"translation": "invalid Object Blob Data."
},
{
"id": "error.structMemNotMatch",
"translation": "Members are not matched in Record or Class"
},
{
"id": "error.invalidComplexTypeName",
"translation": "Invalid descriptor name."
},
{
"id": "error.invalidParamterValue",
"translation": "Invalid parameter value"
},
{
"id": "error.invalidArrayLen",
"translation": "the length of static array is bigger than the one when defined."
},
{
"id": "error.invalidSequenceNumber",
"translation": "Invalid sequence no"
},
{
"id": "error.resultsetInReadOnlyStatus",
"translation": "Resultset in readonly status"
},
{
"id": "error.SSLInitFailed",
"translation": "Failed to initialize SSL"
},
{
"id": "error.LobDataHasFreed",
"translation": "Lob Data has been freed"
},
{
"id": "error.fatalError",
"translation": "Fatal error"
},
{
"id": "error.invalidLenOrOffset",
"translation": "Invalid length or offset"
},
{
"id": "error.intervalValueOverflow",
"translation": "interval type value overflow"
},
{
"id": "error.invalidCipher",
"translation": "Invalid cipher type"
},
{
"id": "error.storeInNilPointer",
"translation": "Can't store value into a nil pointer"
},
{
"id": "error.batchError",
"translation": "Error in executing with batch"
},
{
"id": "warning.bpWithErr",
"translation": "Warning:Partial failure on execute with batch"
},
{
"id": "error.invalidSqlType",
"translation": "Invalid sql type"
},
{
"id": "error.invalidDateTimeValue",
"translation": "Invalid datetime value"
},
{
"id": "error.msgTooLong",
"translation": "Message too long, limit 512M"
},
{
"id": "error.isNull",
"translation": "Data is NULL"
},
{
"id": "error.ParamCountLimit",
"translation": "Parameter count limit is 65536."
},
{
"id": "error.unbindedParameter",
"translation": "Unbound parameter"
},
{
"id": "error.stringCut",
"translation": "The string is cut"
},
{
"id": "error.connectionClosedOrNotBuild",
"translation": "Connection is colsed or not build"
}
]
}`
+248
View File
@@ -0,0 +1,248 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package i18n
const Messages_zh_CN = `{
"language": "zh-Hans",
"messages": [
{
"id": "error.dsn.invalidSchema",
"translation": "DSN串必须以dm://开头"
},
{
"id": "error.dsn.invalidFormat",
"translation": "DSN串格式不正确"
},
{
"id": "error.unsupported.scan",
"translation": "Scan类型转换出错"
},
{
"id": "error.invalidParameterNumber",
"translation": "参数个数不匹配"
},
{
"id": "error.initThirdPartCipherFailed",
"translation": "第三方加密初始化失败"
},
{
"id": "error.connectionSwitchFailed",
"translation": "连接重置失败"
},
{
"id": "error.connectionSwitched",
"translation": "连接已重置"
},
{
"id": "error.invalidServerMode",
"translation": "服务器模式不匹配"
},
{
"id": "error.osauthError",
"translation": "同时使用了指定用户登录和OS认证登录, 请确定一种方式."
},
{
"id": "error.notQuerySQL",
"translation": "非查询SQL语句"
},
{
"id": "error.notExecSQL",
"translation": "非执行SQL语句"
},
{
"id": "error.invalidTranIsolation",
"translation": "非法的事务隔离级"
},
{
"id": "errorCommitInAutoCommitMode",
"translation": "自动提交模式下不能手动提交"
},
{
"id": "errorRollbackInAutoCommitMode",
"translation": "自动提交模式下不能手动回滚"
},
{
"id": "errorStatementHandleClosed",
"translation": "语句已经关闭"
},
{
"id": "errorResultSetColsed",
"translation": "结果集已经关闭"
},
{
"id": "error.communicationError",
"translation": "网络通信异常"
},
{
"id": "error.msgCheckError",
"translation": "消息校验异常"
},
{
"id": "error.unkownNetWork",
"translation": "未知的网络"
},
{
"id": "error.serverVersion",
"translation": "服务器版本太低"
},
{
"id": "error.usernameTooLong",
"translation": "用户名超长"
},
{
"id": "error.passwordTooLong",
"translation": "密码超长"
},
{
"id": "error.dataTooLong",
"translation": "数据大小已超过可支持范围"
},
{
"id": "error.invalidColumnType",
"translation": "无效的列类型"
},
{
"id": "error.dataConvertionError",
"translation": "类型转换异常"
},
{
"id": "error.invalidConn",
"translation": "连接失效"
},
{
"id": "error.invalidHex",
"translation": "无效的十六进制数字"
},
{
"id": "error.invalidBFile",
"translation": "无效的BFile格式串"
},
{
"id": "error.dataOverflow",
"translation": "数字溢出"
},
{
"id": "error.invalidDateTimeFormat",
"translation": "错误的日期时间类型格式"
},
{
"id": "error.datetimeOverflow",
"translation": "数字溢出"
},
{
"id": "error.invalidTimeInterval",
"translation": "错误的时间间隔类型数据"
},
{
"id": "error.unsupportedInparamType",
"translation": "输入参数类型不支持"
},
{
"id": "error.unsupportedOutparamType",
"translation": "输出参数类型不支持"
},
{
"id": "error.unsupportedType",
"translation": "不支持该数据类型"
},
{
"id": "error.invalidObjBlob",
"translation": "无效的对象BLOB数据"
},
{
"id": "error.structMemNotMatch",
"translation": "记录或类数据成员不匹配"
},
{
"id": "error.invalidComplexTypeName",
"translation": "无效的类型描述名称"
},
{
"id": "error.invalidParamterValue",
"translation": "无效的参数值"
},
{
"id": "error.invalidArrayLen",
"translation": "静态数组长度大于定义时长度"
},
{
"id": "error.invalidSequenceNumber",
"translation": "无效的列序号"
},
{
"id": "error.resultsetInReadOnlyStatus",
"translation": "结果集处于只读状态"
},
{
"id": "error.SSLInitFailed",
"translation": "初始化SSL环境失败"
},
{
"id": "error.LobDataHasFreed",
"translation": "LOB数据已经被释放"
},
{
"id": "error.fatalError",
"translation": "致命错误"
},
{
"id": "error.invalidLenOrOffset",
"translation": "长度或偏移错误"
},
{
"id": "error.intervalValueOverflow",
"translation": "时间间隔类型数据溢出"
},
{
"id": "error.invalidCipher",
"translation": "不支持的加密类型"
},
{
"id": "error.storeInNilPointer",
"translation": "无法将数据存入空指针"
},
{
"id": "error.batchError",
"translation": "批量执行出错"
},
{
"id": "warning.bpWithErr",
"translation": "警告:批量执行部分行产生错误"
},
{
"id": "error.invalidSqlType",
"translation": "非法的SQL语句类型"
},
{
"id": "error.invalidDateTimeValue",
"translation": "无效的日期时间类型值"
},
{
"id": "error.msgTooLong",
"translation": "消息长度超出限制512M"
},
{
"id": "error.isNull",
"translation": "数据为NULL"
},
{
"id": "error.ParamCountLimit",
"translation": "参数个数超过最大值65536."
},
{
"id": "error.unbindedParameter",
"translation": "有参数未绑定"
},
{
"id": "error.stringCut",
"translation": "字符串截断"
},
{
"id": "error.connectionClosedOrNotBuild",
"translation": "连接尚未建立或已经关闭"
}
]
}`
+248
View File
@@ -0,0 +1,248 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package i18n
const Messages_zh_HK = `{
"language": "zh-Hant",
"messages": [
{
"id": "error.dsn.invalidSchema",
"translation": "DSN串必須以dm://開頭"
},
{
"id": "error.dsn.invalidFormat",
"translation": "DSN串格式不正確"
},
{
"id": "error.unsupported.scan",
"translation": "Scan類型轉換出錯"
},
{
"id": "error.invalidParameterNumber",
"translation": "參數個數不匹配"
},
{
"id": "error.initThirdPartCipherFailed",
"translation": "第三方加密初始化失敗"
},
{
"id": "error.connectionSwitchFailed",
"translation": "連接重置失敗"
},
{
"id": "error.connectionSwitched",
"translation": "連接已重置"
},
{
"id": "error.invalidServerMode",
"translation": "服務器模式不匹配"
},
{
"id": "error.osauthError",
"translation": "同時使用了指定用戶登錄和OS認證登錄, 請確定一種方式."
},
{
"id": "error.notQuerySQL",
"translation": "非查詢SQL語句"
},
{
"id": "error.notExecSQL",
"translation": "非執行SQL語句"
},
{
"id": "error.invalidTranIsolation",
"translation": "非法的事務隔離級"
},
{
"id": "errorCommitInAutoCommitMode",
"translation": "自動提交模式下不能手動提交"
},
{
"id": "errorRollbackInAutoCommitMode",
"translation": "自動提交模式下不能手動回滾"
},
{
"id": "errorStatementHandleClosed",
"translation": "語句已經關閉"
},
{
"id": "errorResultSetColsed",
"translation": "結果集已經關閉"
},
{
"id": "error.communicationError",
"translation": "網絡通信異常"
},
{
"id": "error.msgCheckError",
"translation": "消息校驗異常"
},
{
"id": "error.unkownNetWork",
"translation": "未知的網絡"
},
{
"id": "error.serverVersion",
"translation": "服務器版本太低"
},
{
"id": "error.usernameTooLong",
"translation": "用戶名超長"
},
{
"id": "error.passwordTooLong",
"translation": "密碼超長"
},
{
"id": "error.dataTooLong",
"translation": "數據大小已超過可支持範圍"
},
{
"id": "error.invalidColumnType",
"translation": "無效的列類型"
},
{
"id": "error.dataConvertionError",
"translation": "類型轉換異常"
},
{
"id": "error.invalidConn",
"translation": "連接失效"
},
{
"id": "error.invalidHex",
"translation": "無效的十六進制数字"
},
{
"id": "error.invalidBFile",
"translation": "無效的BFile格式串"
},
{
"id": "error.dataOverflow",
"translation": "数字溢出"
},
{
"id": "error.invalidDateTimeFormat",
"translation": "錯誤的日期時間類型格式"
},
{
"id": "error.datetimeOverflow",
"translation": "数字溢出"
},
{
"id": "error.invalidTimeInterval",
"translation": "錯誤的時間間隔類型數據"
},
{
"id": "error.unsupportedInparamType",
"translation": "輸入參數類型不支持"
},
{
"id": "error.unsupportedOutparamType",
"translation": "輸出參數類型不支持"
},
{
"id": "error.unsupportedType",
"translation": "不支持該數據類型"
},
{
"id": "error.invalidObjBlob",
"translation": "無效的對象BLOB數據"
},
{
"id": "error.structMemNotMatch",
"translation": "記錄或類數據成員不匹配"
},
{
"id": "error.invalidComplexTypeName",
"translation": "無效的類型描述名稱"
},
{
"id": "error.invalidParamterValue",
"translation": "無效的參數值"
},
{
"id": "error.invalidArrayLen",
"translation": "靜態數組長度大於定義時長度"
},
{
"id": "error.invalidSequenceNumber",
"translation": "無效的列序號"
},
{
"id": "error.resultsetInReadOnlyStatus",
"translation": "結果集處於只讀狀態"
},
{
"id": "error.SSLInitFailed",
"translation": "初始化SSL環境失敗"
},
{
"id": "error.LobDataHasFreed",
"translation": "LOB數據已經被釋放"
},
{
"id": "error.fatalError",
"translation": "致命錯誤"
},
{
"id": "error.invalidLenOrOffset",
"translation": "長度或偏移錯誤"
},
{
"id": "error.intervalValueOverflow",
"translation": "時間間隔類型數據溢出"
},
{
"id": "error.invalidCipher",
"translation": "不支持的加密類型"
},
{
"id": "error.storeInNilPointer",
"translation": "無法將數據存入空指針"
},
{
"id": "error.batchError",
"translation": "批量執行出錯"
},
{
"id": "warning.bpWithErr",
"translation": "警告:批量執行部分行產生錯誤"
},
{
"id": "error.invalidSqlType",
"translation": "非法的SQL語句類型"
},
{
"id": "error.invalidDateTimeValue",
"translation": "無效的日期時間類型值"
},
{
"id": "error.msgTooLong",
"translation": "消息長度超出限制512M"
},
{
"id": "error.isNull",
"translation": "數據為NULL"
},
{
"id": "error.ParamCountLimit",
"translation": "參數個數超過最大值65536."
},
{
"id": "error.unbindedParameter",
"translation": "有參數未綁定"
},
{
"id": "error.stringCut",
"translation": "字符串截斷"
},
{
"id": "error.connectionClosedOrNotBuild",
"translation": "連接尚未建立或已經關閉"
}
]
}`
+270
View File
@@ -0,0 +1,270 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import "database/sql/driver"
type DmArray struct {
TypeData
m_arrDesc *ArrayDescriptor // 数组的描述信息
m_arrData []TypeData // 数组中各行数据值
m_objArray interface{} // 从服务端获取的
m_itemCount int // 本次获取的行数
m_itemSize int // 数组中一个数组项的大小,单位bytes
m_objCount int // 一个数组项中存在对象类型的个数(class、动态数组)
m_strCount int // 一个数组项中存在字符串类型的个数
m_objStrOffs []int // 对象在前,字符串在后
typeName string
elements []interface{}
// Valid为false代表DmArray数据在数据库中为NULL
Valid bool
}
func (da *DmArray) init() *DmArray {
da.initTypeData()
da.m_itemCount = 0
da.m_itemSize = 0
da.m_objCount = 0
da.m_strCount = 0
da.m_objStrOffs = nil
da.m_dumyData = nil
da.m_offset = 0
da.m_objArray = nil
da.Valid = true
return da
}
// 数据库自定义数组Array构造函数,typeName为库中定义的数组类型名称,elements为该数组类型的每个值
//
// 例如,自定义数组类型语句为:create or replace type myArray is array int[];
//
// 则绑入绑出的go对象为: val := dm.NewDmArray("myArray", []interface{} {123, 456})
func NewDmArray(typeName string, elements []interface{}) *DmArray {
da := new(DmArray)
da.typeName = typeName
da.elements = elements
da.Valid = true
return da
}
func (da *DmArray) create(dc *DmConnection) (*DmArray, error) {
desc, err := newArrayDescriptor(da.typeName, dc)
if err != nil {
return nil, err
}
return da.createByArrayDescriptor(desc, dc)
}
func (da *DmArray) createByArrayDescriptor(arrDesc *ArrayDescriptor, conn *DmConnection) (*DmArray, error) {
if nil == arrDesc {
return nil, ECGO_INVALID_PARAMETER_VALUE.throw()
}
da.init()
da.m_arrDesc = arrDesc
if nil == da.elements {
da.m_arrData = make([]TypeData, 0)
} else {
// 若为静态数组,判断给定数组长度是否超过静态数组的上限
if arrDesc.getMDesc() == nil || (arrDesc.getMDesc().getDType() == SARRAY && len(da.elements) > arrDesc.getMDesc().getStaticArrayLength()) {
return nil, ECGO_INVALID_ARRAY_LEN.throw()
}
var err error
da.m_arrData, err = TypeDataSV.toArray(da.elements, da.m_arrDesc.getMDesc())
if err != nil {
return nil, err
}
}
da.m_itemCount = len(da.m_arrData)
return da, nil
}
func newDmArrayByTypeData(atData []TypeData, desc *TypeDescriptor) *DmArray {
da := new(DmArray)
da.init()
da.m_arrDesc = newArrayDescriptorByTypeDescriptor(desc)
da.m_arrData = atData
return da
}
func (da *DmArray) checkIndex(index int64) error {
if index < 0 || index > int64(len(da.m_arrData)-1) {
return ECGO_INVALID_LENGTH_OR_OFFSET.throw()
}
return nil
}
func (da *DmArray) checkIndexAndCount(index int64, count int) error {
err := da.checkIndex(index)
if err != nil {
return err
}
if count <= 0 || index+int64(count) > int64(len(da.m_arrData)) {
return ECGO_INVALID_LENGTH_OR_OFFSET.throw()
}
return nil
}
// 获取Array对象在数据库中的类型名称
func (da *DmArray) GetBaseTypeName() (string, error) {
if err := da.checkValid(); err != nil {
return "", err
}
return da.m_arrDesc.m_typeDesc.getFulName()
}
// 获取Array对象的go数组对象
func (da *DmArray) GetArray() (interface{}, error) {
if da.m_arrData == nil || len(da.m_arrData) <= 0 {
return nil, nil;
}
return TypeDataSV.toJavaArray(da, 0, len(da.m_arrData), da.m_arrDesc.getItemDesc().getDType())
}
// 获取Array对象的指定偏移和执行长度go数据对象 index从0开始
func (da *DmArray) GetObjArray(index int64, count int) (interface{}, error) {
var err error
if err = da.checkValid(); err != nil {
return nil, err
}
if err = da.checkIndexAndCount(index, count); err != nil {
return nil, err
}
return TypeDataSV.toJavaArray(da, index, count, da.m_arrDesc.getItemDesc().getDType())
}
func (da *DmArray) GetIntArray(index int64, count int) ([]int, error) {
var err error
if err = da.checkValid(); err != nil {
return nil, err
}
if err = da.checkIndexAndCount(index, count); err != nil {
return nil, err
}
tmp, err := TypeDataSV.toNumericArray(da, index, count, ARRAY_TYPE_INTEGER)
if err != nil {
return nil, err
}
return tmp.([]int), nil
}
func (da *DmArray) GetInt16Array(index int64, count int) ([]int16, error) {
var err error
if err = da.checkValid(); err != nil {
return nil, err
}
if err = da.checkIndexAndCount(index, count); err != nil {
return nil, err
}
tmp, err := TypeDataSV.toNumericArray(da, index, count, ARRAY_TYPE_SHORT)
if err != nil {
return nil, err
}
return tmp.([]int16), nil
}
func (da *DmArray) GetInt64Array(index int64, count int) ([]int64, error) {
var err error
if err = da.checkValid(); err != nil {
return nil, err
}
if err = da.checkIndexAndCount(index, count); err != nil {
return nil, err
}
tmp, err := TypeDataSV.toNumericArray(da, index, count, ARRAY_TYPE_LONG)
if err != nil {
return nil, err
}
return tmp.([]int64), nil
}
func (da *DmArray) GetFloatArray(index int64, count int) ([]float32, error) {
var err error
if err = da.checkValid(); err != nil {
return nil, err
}
if err = da.checkIndexAndCount(index, count); err != nil {
return nil, err
}
tmp, err := TypeDataSV.toNumericArray(da, index, count, ARRAY_TYPE_FLOAT)
if err != nil {
return nil, err
}
return tmp.([]float32), nil
}
func (da *DmArray) GetDoubleArray(index int64, count int) ([]float64, error) {
var err error
if err = da.checkValid(); err != nil {
return nil, err
}
if err = da.checkIndexAndCount(index, count); err != nil {
return nil, err
}
tmp, err := TypeDataSV.toNumericArray(da, index, count, ARRAY_TYPE_DOUBLE)
if err != nil {
return nil, err
}
return tmp.([]float64), nil
}
func (dest *DmArray) Scan(src interface{}) error {
if dest == nil {
return ECGO_STORE_IN_NIL_POINTER.throw()
}
switch src := src.(type) {
case nil:
*dest = *new(DmArray)
// 将Valid标志置false表示数据库中该列为NULL
(*dest).Valid = false
return nil
case *DmArray:
*dest = *src
return nil
default:
return UNSUPPORTED_SCAN.throw()
}
}
func (array DmArray) Value() (driver.Value, error) {
if !array.Valid {
return nil, nil
}
return array, nil
}
func (array *DmArray) checkValid() error {
if !array.Valid {
return ECGO_IS_NULL.throw()
}
return nil
}
+297
View File
@@ -0,0 +1,297 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"database/sql/driver"
"io"
)
type DmBlob struct {
lob
data []byte
offset int64
}
func newDmBlob() *DmBlob {
return &DmBlob{
lob: lob{
inRow: true,
groupId: -1,
fileId: -1,
pageNo: -1,
readOver: false,
local: true,
updateable: true,
length: -1,
compatibleOracle: false,
fetchAll: false,
freed: false,
modify: false,
Valid: true,
},
offset: 1,
}
}
func newBlobFromDB(value []byte, conn *DmConnection, column *column, fetchAll bool) *DmBlob {
var blob = newDmBlob()
blob.connection = conn
blob.lobFlag = LOB_FLAG_BYTE
blob.compatibleOracle = conn.CompatibleOracle()
blob.local = false
blob.updateable = !column.readonly
blob.tabId = column.lobTabId
blob.colId = column.lobColId
blob.inRow = Dm_build_1346.Dm_build_1439(value, NBLOB_HEAD_IN_ROW_FLAG) == LOB_IN_ROW
blob.blobId = Dm_build_1346.Dm_build_1453(value, NBLOB_HEAD_BLOBID)
if !blob.inRow {
blob.groupId = Dm_build_1346.Dm_build_1443(value, NBLOB_HEAD_OUTROW_GROUPID)
blob.fileId = Dm_build_1346.Dm_build_1443(value, NBLOB_HEAD_OUTROW_FILEID)
blob.pageNo = Dm_build_1346.Dm_build_1448(value, NBLOB_HEAD_OUTROW_PAGENO)
}
if conn.NewLobFlag {
blob.tabId = Dm_build_1346.Dm_build_1448(value, NBLOB_EX_HEAD_TABLE_ID)
blob.colId = Dm_build_1346.Dm_build_1443(value, NBLOB_EX_HEAD_COL_ID)
blob.rowId = Dm_build_1346.Dm_build_1453(value, NBLOB_EX_HEAD_ROW_ID)
blob.exGroupId = Dm_build_1346.Dm_build_1443(value, NBLOB_EX_HEAD_FPA_GRPID)
blob.exFileId = Dm_build_1346.Dm_build_1443(value, NBLOB_EX_HEAD_FPA_FILEID)
blob.exPageNo = Dm_build_1346.Dm_build_1448(value, NBLOB_EX_HEAD_FPA_PAGENO)
}
blob.resetCurrentInfo()
blob.length = blob.getLengthFromHead(value)
if blob.inRow {
blob.data = make([]byte, blob.length)
if conn.NewLobFlag {
Dm_build_1346.Dm_build_1402(blob.data, 0, value, NBLOB_EX_HEAD_SIZE, len(blob.data))
} else {
Dm_build_1346.Dm_build_1402(blob.data, 0, value, NBLOB_INROW_HEAD_SIZE, len(blob.data))
}
} else if fetchAll {
blob.loadAllData()
}
return blob
}
func newBlobOfLocal(value []byte, conn *DmConnection) *DmBlob {
var blob = newDmBlob()
blob.connection = conn
blob.lobFlag = LOB_FLAG_BYTE
blob.data = value
blob.length = int64(len(blob.data))
return blob
}
func NewBlob(value []byte) *DmBlob {
var blob = newDmBlob()
blob.lobFlag = LOB_FLAG_BYTE
blob.data = value
blob.length = int64(len(blob.data))
return blob
}
func (blob *DmBlob) Read(dest []byte) (n int, err error) {
if err = blob.checkValid(); err != nil {
return
}
result, err := blob.getBytes(blob.offset, int32(len(dest)))
if err != nil {
return 0, err
}
blob.offset += int64(len(result))
copy(dest, result)
if len(result) == 0 {
return 0, io.EOF
}
return len(result), nil
}
func (blob *DmBlob) ReadAt(pos int, dest []byte) (n int, err error) {
if err = blob.checkValid(); err != nil {
return
}
result, err := blob.getBytes(int64(pos), int32(len(dest)))
if err != nil {
return 0, err
}
if len(result) == 0 {
return 0, io.EOF
}
copy(dest[0:len(result)], result)
return len(result), nil
}
func (blob *DmBlob) Write(pos int, src []byte) (n int, err error) {
if err = blob.checkValid(); err != nil {
return
}
if err = blob.checkFreed(); err != nil {
return
}
if pos < 1 {
err = ECGO_INVALID_LENGTH_OR_OFFSET.throw()
return
}
if !blob.updateable {
err = ECGO_RESULTSET_IS_READ_ONLY.throw()
return
}
pos -= 1
if blob.local || blob.fetchAll {
if int64(pos) > blob.length {
err = ECGO_INVALID_LENGTH_OR_OFFSET.throw()
return
}
blob.setLocalData(pos, src)
n = len(src)
} else {
if err = blob.connection.checkClosed(); err != nil {
return -1, err
}
var writeLen, err = blob.connection.Access.dm_build_638(blob, pos, src)
if err != nil {
return -1, err
}
if blob.groupId == -1 {
blob.setLocalData(pos, src)
} else {
blob.inRow = false
blob.length = -1
}
n = writeLen
}
blob.modify = true
return
}
func (blob *DmBlob) Truncate(length int64) error {
var err error
if err = blob.checkValid(); err != nil {
return err
}
if err = blob.checkFreed(); err != nil {
return err
}
if length < 0 {
return ECGO_INVALID_LENGTH_OR_OFFSET.throw()
}
if !blob.updateable {
return ECGO_RESULTSET_IS_READ_ONLY.throw()
}
if blob.local || blob.fetchAll {
if length > int64(len(blob.data)) {
return ECGO_INVALID_LENGTH_OR_OFFSET.throw()
}
if length == int64(len(blob.data)) {
return nil
}
tmp := make([]byte, length)
Dm_build_1346.Dm_build_1402(tmp, 0, blob.data, 0, len(tmp))
blob.data = tmp
blob.length = int64(len(tmp))
} else {
if err = blob.connection.checkClosed(); err != nil {
return err
}
blob.length, err = blob.connection.Access.dm_build_652(&blob.lob, int(length))
if err != nil {
return err
}
if blob.groupId == -1 {
tmp := make([]byte, blob.length)
Dm_build_1346.Dm_build_1402(tmp, 0, blob.data, 0, int(blob.length))
blob.data = tmp
}
}
blob.modify = true
return nil
}
func (dest *DmBlob) Scan(src interface{}) error {
if dest == nil {
return ECGO_STORE_IN_NIL_POINTER.throw()
}
switch src := src.(type) {
case nil:
*dest = *new(DmBlob)
(*dest).Valid = false
return nil
case []byte:
*dest = *NewBlob(src)
return nil
case *DmBlob:
*dest = *src
return nil
default:
return UNSUPPORTED_SCAN.throw()
}
}
func (blob DmBlob) Value() (driver.Value, error) {
if !blob.Valid {
return nil, nil
}
return blob, nil
}
func (blob *DmBlob) getBytes(pos int64, length int32) ([]byte, error) {
var err error
var leaveLength int64
if err = blob.checkFreed(); err != nil {
return nil, err
}
if pos < 1 || length < 0 {
return nil, ECGO_INVALID_LENGTH_OR_OFFSET.throw()
}
pos = pos - 1
if leaveLength, err = blob.GetLength(); err != nil {
return nil, err
}
leaveLength -= pos
if leaveLength < 0 {
return nil, ECGO_INVALID_LENGTH_OR_OFFSET.throw()
}
if int64(length) > leaveLength {
length = int32(leaveLength)
}
if blob.local || blob.inRow || blob.fetchAll {
return blob.data[pos : pos+int64(length)], nil
} else {
return blob.connection.Access.dm_build_599(blob, int32(pos), length)
}
}
func (blob *DmBlob) loadAllData() {
blob.checkFreed()
if blob.local || blob.inRow || blob.fetchAll {
return
}
len, _ := blob.GetLength()
blob.data, _ = blob.getBytes(1, int32(len))
blob.fetchAll = true
}
func (blob *DmBlob) setLocalData(pos int, p []byte) {
if pos+len(p) >= int(blob.length) {
var tmp = make([]byte, pos+len(p))
Dm_build_1346.Dm_build_1402(tmp, 0, blob.data, 0, pos)
Dm_build_1346.Dm_build_1402(tmp, pos, p, 0, len(p))
blob.data = tmp
} else {
Dm_build_1346.Dm_build_1402(blob.data, pos, p, 0, len(p))
}
blob.length = int64(len(blob.data))
}
func (d *DmBlob) GormDataType() string {
return "BLOB"
}
+279
View File
@@ -0,0 +1,279 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"database/sql/driver"
"io"
)
type DmClob struct {
lob
data []rune
serverEncoding string
}
func newDmClob() *DmClob {
return &DmClob{
lob: lob{
inRow: true,
groupId: -1,
fileId: -1,
pageNo: -1,
readOver: false,
local: true,
updateable: true,
length: -1,
compatibleOracle: false,
fetchAll: false,
freed: false,
modify: false,
Valid: true,
},
}
}
func newClobFromDB(value []byte, conn *DmConnection, column *column, fetchAll bool) *DmClob {
var clob = newDmClob()
clob.connection = conn
clob.lobFlag = LOB_FLAG_CHAR
clob.compatibleOracle = conn.CompatibleOracle()
clob.local = false
clob.updateable = !column.readonly
clob.tabId = column.lobTabId
clob.colId = column.lobColId
clob.inRow = Dm_build_1346.Dm_build_1439(value, NBLOB_HEAD_IN_ROW_FLAG) == LOB_IN_ROW
clob.blobId = Dm_build_1346.Dm_build_1453(value, NBLOB_HEAD_BLOBID)
if !clob.inRow {
clob.groupId = Dm_build_1346.Dm_build_1443(value, NBLOB_HEAD_OUTROW_GROUPID)
clob.fileId = Dm_build_1346.Dm_build_1443(value, NBLOB_HEAD_OUTROW_FILEID)
clob.pageNo = Dm_build_1346.Dm_build_1448(value, NBLOB_HEAD_OUTROW_PAGENO)
}
if conn.NewLobFlag {
clob.tabId = Dm_build_1346.Dm_build_1448(value, NBLOB_EX_HEAD_TABLE_ID)
clob.colId = Dm_build_1346.Dm_build_1443(value, NBLOB_EX_HEAD_COL_ID)
clob.rowId = Dm_build_1346.Dm_build_1453(value, NBLOB_EX_HEAD_ROW_ID)
clob.exGroupId = Dm_build_1346.Dm_build_1443(value, NBLOB_EX_HEAD_FPA_GRPID)
clob.exFileId = Dm_build_1346.Dm_build_1443(value, NBLOB_EX_HEAD_FPA_FILEID)
clob.exPageNo = Dm_build_1346.Dm_build_1448(value, NBLOB_EX_HEAD_FPA_PAGENO)
}
clob.resetCurrentInfo()
clob.serverEncoding = conn.getServerEncoding()
if clob.inRow {
if conn.NewLobFlag {
clob.data = []rune(Dm_build_1346.Dm_build_1503(value, NBLOB_EX_HEAD_SIZE, int(clob.getLengthFromHead(value)), clob.serverEncoding, conn))
} else {
clob.data = []rune(Dm_build_1346.Dm_build_1503(value, NBLOB_INROW_HEAD_SIZE, int(clob.getLengthFromHead(value)), clob.serverEncoding, conn))
}
clob.length = int64(len(clob.data))
} else if fetchAll {
clob.loadAllData()
}
return clob
}
func newClobOfLocal(value string, conn *DmConnection) *DmClob {
var clob = newDmClob()
clob.connection = conn
clob.lobFlag = LOB_FLAG_CHAR
clob.data = []rune(value)
clob.length = int64(len(clob.data))
return clob
}
func NewClob(value string) *DmClob {
var clob = newDmClob()
clob.lobFlag = LOB_FLAG_CHAR
clob.data = []rune(value)
clob.length = int64(len(clob.data))
return clob
}
func (clob *DmClob) ReadString(pos int, length int) (result string, err error) {
if err = clob.checkValid(); err != nil {
return
}
result, err = clob.getSubString(int64(pos), int32(length))
if err != nil {
return
}
if len(result) == 0 {
err = io.EOF
return
}
return
}
func (clob *DmClob) WriteString(pos int, s string) (n int, err error) {
if err = clob.checkValid(); err != nil {
return
}
if err = clob.checkFreed(); err != nil {
return
}
if pos < 1 {
err = ECGO_INVALID_LENGTH_OR_OFFSET.throw()
return
}
if !clob.updateable {
err = ECGO_RESULTSET_IS_READ_ONLY.throw()
return
}
pos -= 1
if clob.local || clob.fetchAll {
if int64(pos) > clob.length {
err = ECGO_INVALID_LENGTH_OR_OFFSET.throw()
return
}
clob.setLocalData(pos, s)
n = len(s)
} else {
if err = clob.connection.checkClosed(); err != nil {
return -1, err
}
var writeLen, err = clob.connection.Access.dm_build_622(clob, pos, s, clob.serverEncoding)
if err != nil {
return -1, err
}
if clob.groupId == -1 {
clob.setLocalData(pos, s)
} else {
clob.inRow = false
clob.length = -1
}
n = writeLen
}
clob.modify = true
return
}
func (clob *DmClob) Truncate(length int64) error {
var err error
if err = clob.checkValid(); err != nil {
return err
}
if err = clob.checkFreed(); err != nil {
return err
}
if length < 0 {
return ECGO_INVALID_LENGTH_OR_OFFSET.throw()
}
if !clob.updateable {
return ECGO_RESULTSET_IS_READ_ONLY.throw()
}
if clob.local || clob.fetchAll {
if length > int64(len(clob.data)) {
return ECGO_INVALID_LENGTH_OR_OFFSET.throw()
}
if length == int64(len(clob.data)) {
return nil
}
clob.data = clob.data[0:length]
clob.length = int64(len(clob.data))
} else {
if err = clob.connection.checkClosed(); err != nil {
return err
}
clob.length, err = clob.connection.Access.dm_build_652(&clob.lob, int(length))
if err != nil {
return err
}
if clob.groupId == -1 {
clob.data = clob.data[0:clob.length]
}
}
clob.modify = true
return nil
}
func (dest *DmClob) Scan(src interface{}) error {
if dest == nil {
return ECGO_STORE_IN_NIL_POINTER.throw()
}
switch src := src.(type) {
case nil:
*dest = *new(DmClob)
(*dest).Valid = false
return nil
case string:
*dest = *NewClob(src)
return nil
case *DmClob:
*dest = *src
return nil
default:
return UNSUPPORTED_SCAN.throw()
}
}
func (clob DmClob) Value() (driver.Value, error) {
if !clob.Valid {
return nil, nil
}
return clob, nil
}
func (clob *DmClob) getSubString(pos int64, len int32) (string, error) {
var err error
var leaveLength int64
if err = clob.checkFreed(); err != nil {
return "", err
}
if pos < 1 || len < 0 {
return "", ECGO_INVALID_LENGTH_OR_OFFSET.throw()
}
pos = pos - 1
if leaveLength, err = clob.GetLength(); err != nil {
return "", err
}
if pos > leaveLength {
pos = leaveLength
}
leaveLength -= pos
if leaveLength < 0 {
return "", ECGO_INVALID_LENGTH_OR_OFFSET.throw()
}
if int64(len) > leaveLength {
len = int32(leaveLength)
}
if clob.local || clob.inRow || clob.fetchAll {
if pos > clob.length {
return "", ECGO_INVALID_LENGTH_OR_OFFSET.throw()
}
return string(clob.data[pos : pos+int64(len)]), nil
} else {
return clob.connection.Access.dm_build_610(clob, int32(pos), len)
}
}
func (clob *DmClob) loadAllData() {
clob.checkFreed()
if clob.local || clob.inRow || clob.fetchAll {
return
}
len, _ := clob.GetLength()
s, _ := clob.getSubString(1, int32(len))
clob.data = []rune(s)
clob.fetchAll = true
}
func (clob *DmClob) setLocalData(pos int, str string) {
if pos+len(str) >= int(clob.length) {
clob.data = []rune(string(clob.data[0:pos]) + str)
} else {
clob.data = []rune(string(clob.data[0:pos]) + str + string(clob.data[pos+len(str):len(clob.data)]))
}
clob.length = int64(len(clob.data))
}
func (d *DmClob) GormDataType() string {
return "CLOB"
}
+874
View File
@@ -0,0 +1,874 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"bytes"
"context"
"database/sql"
"database/sql/driver"
"fmt"
"sync"
"sync/atomic"
"gitee.com/chunanyong/dm/parser"
"gitee.com/chunanyong/dm/util"
"golang.org/x/text/encoding"
)
type DmConnection struct {
filterable
mu sync.Mutex
dmConnector *DmConnector
Access *dm_build_414
stmtMap map[int32]*DmStatement
lastExecInfo *execRetInfo
lexer *parser.Lexer
encode encoding.Encoding
encodeBuffer *bytes.Buffer
transformReaderDst []byte
transformReaderSrc []byte
serverEncoding string
GlobalServerSeries int
ServerVersion string
Malini2 bool
Execute2 bool
LobEmptyCompOrcl bool
IsoLevel int32
ReadOnly bool
NewLobFlag bool
sslEncrypt int
MaxRowSize int32
DDLAutoCommit bool
BackSlashFlag bool
SvrStat int32
SvrMode int32
ConstParaOpt bool
DbTimezone int16
LifeTimeRemainder int16
InstanceName string
Schema string
LastLoginIP string
LastLoginTime string
FailedAttempts int32
LoginWarningID int32
GraceTimeRemainder int32
Guid string
DbName string
StandbyHost string
StandbyPort int32
StandbyCount int32
SessionID int64
OracleDateLanguage byte
FormatDate string
FormatTimestamp string
FormatTimestampTZ string
FormatTime string
FormatTimeTZ string
Local bool
MsgVersion int32
TrxStatus int32
dscControl bool
trxFinish bool
autoCommit bool
isBatch bool
watching bool
watcher chan<- context.Context
closech chan struct{}
finished chan<- struct{}
canceled atomicError
closed atomicBool
}
func (conn *DmConnection) setTrxFinish(status int32) {
switch status & Dm_build_825 {
case Dm_build_822, Dm_build_823, Dm_build_824:
conn.trxFinish = true
default:
conn.trxFinish = false
}
}
func (dmConn *DmConnection) init() {
dmConn.stmtMap = make(map[int32]*DmStatement)
dmConn.DbTimezone = 0
dmConn.GlobalServerSeries = 0
dmConn.MaxRowSize = 0
dmConn.LobEmptyCompOrcl = false
dmConn.ReadOnly = false
dmConn.DDLAutoCommit = false
dmConn.ConstParaOpt = false
dmConn.IsoLevel = -1
dmConn.Malini2 = true
dmConn.NewLobFlag = true
dmConn.Execute2 = true
dmConn.serverEncoding = ENCODING_GB18030
dmConn.TrxStatus = Dm_build_773
dmConn.setTrxFinish(dmConn.TrxStatus)
dmConn.OracleDateLanguage = byte(Locale)
dmConn.lastExecInfo = NewExceInfo()
dmConn.MsgVersion = Dm_build_706
dmConn.idGenerator = dmConnIDGenerator
}
func (dmConn *DmConnection) reset() {
dmConn.DbTimezone = 0
dmConn.GlobalServerSeries = 0
dmConn.MaxRowSize = 0
dmConn.LobEmptyCompOrcl = false
dmConn.ReadOnly = false
dmConn.DDLAutoCommit = false
dmConn.ConstParaOpt = false
dmConn.IsoLevel = -1
dmConn.Malini2 = true
dmConn.NewLobFlag = true
dmConn.Execute2 = true
dmConn.serverEncoding = ENCODING_GB18030
dmConn.TrxStatus = Dm_build_773
dmConn.setTrxFinish(dmConn.TrxStatus)
}
func (dc *DmConnection) checkClosed() error {
if dc.closed.IsSet() {
return driver.ErrBadConn
}
return nil
}
func (dc *DmConnection) executeInner(query string, execType int16) (interface{}, error) {
stmt, err := NewDmStmt(dc, query)
if err != nil {
return nil, err
}
if execType == Dm_build_790 {
defer stmt.close()
}
stmt.innerUsed = true
var escapeSql = query
if stmt.dmConn.dmConnector.escapeProcess {
escapeSql, err = stmt.dmConn.escape(escapeSql, stmt.dmConn.dmConnector.keyWords)
if err != nil {
stmt.close()
return nil, err
}
}
stmt.nativeSql = escapeSql
var optParamList []OptParameter
if stmt.dmConn.ConstParaOpt {
optParamList = make([]OptParameter, 0)
stmt.nativeSql, optParamList, err = stmt.dmConn.execOpt(stmt.nativeSql, optParamList, stmt.dmConn.getServerEncoding(), stmt.dmConn.BackSlashFlag)
}
if execType == Dm_build_789 && dc.dmConnector.enRsCache {
rpv, err := rp.get(stmt, query)
if err != nil {
return nil, err
}
if rpv != nil {
stmt.execInfo = rpv.execInfo
dc.lastExecInfo = rpv.execInfo
return newDmRows(rpv.getResultSet(stmt)), nil
}
}
var info *execRetInfo
if optParamList != nil && len(optParamList) > 0 {
info, err = dc.Access.Dm_build_497(stmt, optParamList)
if err != nil {
stmt.nativeSql = escapeSql
info, err = dc.Access.Dm_build_503(stmt, execType)
}
} else {
info, err = dc.Access.Dm_build_503(stmt, execType)
}
if err != nil {
stmt.close()
return nil, err
}
dc.lastExecInfo = info
if execType == Dm_build_789 && info.hasResultSet {
return newDmRows(newInnerRows(0, stmt, info)), nil
} else {
return newDmResult(stmt, info), nil
}
}
func g2dbIsoLevel(isoLevel int32) int32 {
switch isoLevel {
case 1:
return Dm_build_777
case 2:
return Dm_build_778
case 4:
return Dm_build_779
case 6:
return Dm_build_780
default:
return -1
}
}
func (dc *DmConnection) Begin() (driver.Tx, error) {
if len(dc.filterChain.filters) == 0 {
return dc.begin()
} else {
return dc.filterChain.reset().DmConnectionBegin(dc)
}
}
func (dc *DmConnection) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
if len(dc.filterChain.filters) == 0 {
return dc.beginTx(ctx, opts)
}
return dc.filterChain.reset().DmConnectionBeginTx(dc, ctx, opts)
}
func (dc *DmConnection) Commit() error {
if len(dc.filterChain.filters) == 0 {
return dc.commit()
} else {
return dc.filterChain.reset().DmConnectionCommit(dc)
}
}
func (dc *DmConnection) Rollback() error {
if len(dc.filterChain.filters) == 0 {
return dc.rollback()
} else {
return dc.filterChain.reset().DmConnectionRollback(dc)
}
}
func (dc *DmConnection) Close() error {
if len(dc.filterChain.filters) == 0 {
return dc.close()
} else {
return dc.filterChain.reset().DmConnectionClose(dc)
}
}
func (dc *DmConnection) Ping(ctx context.Context) error {
if len(dc.filterChain.filters) == 0 {
return dc.ping(ctx)
} else {
return dc.filterChain.reset().DmConnectionPing(dc, ctx)
}
}
func (dc *DmConnection) Exec(query string, args []driver.Value) (driver.Result, error) {
if len(dc.filterChain.filters) == 0 {
return dc.exec(query, args)
}
return dc.filterChain.reset().DmConnectionExec(dc, query, args)
}
func (dc *DmConnection) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
if len(dc.filterChain.filters) == 0 {
return dc.execContext(ctx, query, args)
}
return dc.filterChain.reset().DmConnectionExecContext(dc, ctx, query, args)
}
func (dc *DmConnection) Query(query string, args []driver.Value) (driver.Rows, error) {
if len(dc.filterChain.filters) == 0 {
return dc.query(query, args)
}
return dc.filterChain.reset().DmConnectionQuery(dc, query, args)
}
func (dc *DmConnection) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {
if len(dc.filterChain.filters) == 0 {
return dc.queryContext(ctx, query, args)
}
return dc.filterChain.reset().DmConnectionQueryContext(dc, ctx, query, args)
}
func (dc *DmConnection) Prepare(query string) (driver.Stmt, error) {
if len(dc.filterChain.filters) == 0 {
return dc.prepare(query)
}
return dc.filterChain.reset().DmConnectionPrepare(dc, query)
}
func (dc *DmConnection) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) {
if len(dc.filterChain.filters) == 0 {
return dc.prepareContext(ctx, query)
}
return dc.filterChain.reset().DmConnectionPrepareContext(dc, ctx, query)
}
func (dc *DmConnection) ResetSession(ctx context.Context) error {
if len(dc.filterChain.filters) == 0 {
return dc.resetSession(ctx)
}
if err := dc.filterChain.reset().DmConnectionResetSession(dc, ctx); err != nil {
return driver.ErrBadConn
} else {
return nil
}
}
func (dc *DmConnection) CheckNamedValue(nv *driver.NamedValue) error {
if len(dc.filterChain.filters) == 0 {
return dc.checkNamedValue(nv)
}
return dc.filterChain.reset().DmConnectionCheckNamedValue(dc, nv)
}
func (dc *DmConnection) begin() (*DmConnection, error) {
return dc.beginTx(context.Background(), driver.TxOptions{driver.IsolationLevel(sql.LevelDefault), false})
}
func (dc *DmConnection) beginTx(ctx context.Context, opts driver.TxOptions) (*DmConnection, error) {
if err := dc.watchCancel(ctx); err != nil {
return nil, err
}
defer dc.finish()
err := dc.checkClosed()
if err != nil {
return nil, err
}
dc.autoCommit = false
if dc.ReadOnly != opts.ReadOnly {
dc.ReadOnly = opts.ReadOnly
var readonly = 0
if opts.ReadOnly {
readonly = 1
}
dc.exec(fmt.Sprintf("SP_SET_SESSION_READONLY(%d)", readonly), nil)
}
if dc.IsoLevel != int32(opts.Isolation) {
switch sql.IsolationLevel(opts.Isolation) {
case sql.LevelDefault:
dc.IsoLevel = int32(sql.LevelReadCommitted)
case sql.LevelReadUncommitted, sql.LevelReadCommitted, sql.LevelSerializable:
dc.IsoLevel = int32(opts.Isolation)
case sql.LevelRepeatableRead:
if dc.CompatibleMysql() {
dc.IsoLevel = int32(sql.LevelReadCommitted)
} else {
return nil, ECGO_INVALID_TRAN_ISOLATION.throw()
}
default:
return nil, ECGO_INVALID_TRAN_ISOLATION.throw()
}
err = dc.Access.Dm_build_565(dc)
if err != nil {
return nil, err
}
}
return dc, nil
}
func (dc *DmConnection) commit() error {
err := dc.checkClosed()
if err != nil {
return err
}
defer func() {
dc.autoCommit = dc.dmConnector.autoCommit
if dc.ReadOnly {
dc.exec("SP_SET_SESSION_READONLY(0)", nil)
}
}()
if !dc.autoCommit || !dc.trxFinish {
err = dc.Access.Commit()
if err != nil {
return err
}
dc.trxFinish = true
return nil
} else if !dc.dmConnector.alwayseAllowCommit {
return ECGO_COMMIT_IN_AUTOCOMMIT_MODE.throw()
}
return nil
}
func (dc *DmConnection) rollback() error {
err := dc.checkClosed()
if err != nil {
return err
}
defer func() {
dc.autoCommit = dc.dmConnector.autoCommit
if dc.ReadOnly {
dc.exec("SP_SET_SESSION_READONLY(0)", nil)
}
}()
if !dc.autoCommit {
err = dc.Access.Rollback()
if err != nil {
return err
}
dc.trxFinish = true
return nil
} else if !dc.dmConnector.alwayseAllowCommit {
return ECGO_ROLLBACK_IN_AUTOCOMMIT_MODE.throw()
}
return nil
}
func (dc *DmConnection) reconnect() error {
err := dc.Access.Close()
if err != nil {
return err
}
for _, stmt := range dc.stmtMap {
for id, rs := range stmt.rsMap {
rs.Close()
delete(stmt.rsMap, id)
}
}
var newConn *DmConnection
if dc.dmConnector.group != nil {
if newConn, err = dc.dmConnector.group.connect(dc.dmConnector); err != nil {
return err
}
} else {
newConn, err = dc.dmConnector.connect(context.Background())
}
oldMap := dc.stmtMap
newConn.mu = dc.mu
newConn.filterable = dc.filterable
*dc = *newConn
for _, stmt := range oldMap {
if stmt.closed {
continue
}
err = dc.Access.Dm_build_475(stmt)
if err != nil {
stmt.free()
continue
}
if stmt.prepared || stmt.paramCount > 0 {
if err = stmt.prepare(); err != nil {
continue
}
}
dc.stmtMap[stmt.id] = stmt
}
return nil
}
func (dc *DmConnection) cleanup() {
dc.close()
}
func (dc *DmConnection) close() error {
if !dc.closed.TrySet(true) {
return nil
}
util.AbsorbPanic(func() {
close(dc.closech)
})
if dc.Access == nil {
return nil
}
dc.rollback()
for _, stmt := range dc.stmtMap {
stmt.free()
}
dc.Access.Close()
return nil
}
func (dc *DmConnection) ping(ctx context.Context) error {
if err := dc.watchCancel(ctx); err != nil {
return err
}
defer dc.finish()
rows, err := dc.query("select 1", nil)
if err != nil {
return err
}
return rows.close()
}
func (dc *DmConnection) exec(query string, args []driver.Value) (*DmResult, error) {
err := dc.checkClosed()
if err != nil {
return nil, err
}
if args != nil && len(args) > 0 {
stmt, err := dc.prepare(query)
if err != nil {
return nil, err
}
defer stmt.close()
dc.lastExecInfo = stmt.execInfo
return stmt.exec(args)
} else {
r1, err := dc.executeInner(query, Dm_build_790)
if err != nil {
return nil, err
}
if r2, ok := r1.(*DmResult); ok {
return r2, nil
} else {
return nil, ECGO_NOT_EXEC_SQL.throw()
}
}
}
func (dc *DmConnection) execContext(ctx context.Context, query string, args []driver.NamedValue) (*DmResult, error) {
if err := dc.watchCancel(ctx); err != nil {
return nil, err
}
defer dc.finish()
err := dc.checkClosed()
if err != nil {
return nil, err
}
if args != nil && len(args) > 0 {
stmt, err := dc.prepare(query)
if err != nil {
return nil, err
}
defer stmt.close()
dc.lastExecInfo = stmt.execInfo
dargs, err := namedValueToValue(stmt, args)
if err != nil {
return nil, err
}
return stmt.exec(dargs)
} else {
r1, err := dc.executeInner(query, Dm_build_790)
if err != nil {
return nil, err
}
if r2, ok := r1.(*DmResult); ok {
return r2, nil
} else {
return nil, ECGO_NOT_EXEC_SQL.throw()
}
}
}
func (dc *DmConnection) query(query string, args []driver.Value) (*DmRows, error) {
err := dc.checkClosed()
if err != nil {
return nil, err
}
if args != nil && len(args) > 0 {
stmt, err := dc.prepare(query)
if err != nil {
return nil, err
}
dc.lastExecInfo = stmt.execInfo
stmt.innerUsed = true
return stmt.query(args)
} else {
r1, err := dc.executeInner(query, Dm_build_789)
if err != nil {
return nil, err
}
if r2, ok := r1.(*DmRows); ok {
return r2, nil
} else {
return nil, ECGO_NOT_QUERY_SQL.throw()
}
}
}
func (dc *DmConnection) queryContext(ctx context.Context, query string, args []driver.NamedValue) (*DmRows, error) {
if err := dc.watchCancel(ctx); err != nil {
return nil, err
}
defer dc.finish()
err := dc.checkClosed()
if err != nil {
return nil, err
}
if args != nil && len(args) > 0 {
stmt, err := dc.prepare(query)
if err != nil {
return nil, err
}
dc.lastExecInfo = stmt.execInfo
stmt.innerUsed = true
dargs, err := namedValueToValue(stmt, args)
if err != nil {
return nil, err
}
return stmt.query(dargs)
} else {
r1, err := dc.executeInner(query, Dm_build_789)
if err != nil {
return nil, err
}
if r2, ok := r1.(*DmRows); ok {
return r2, nil
} else {
return nil, ECGO_NOT_QUERY_SQL.throw()
}
}
}
func (dc *DmConnection) prepare(query string) (stmt *DmStatement, err error) {
if err = dc.checkClosed(); err != nil {
return
}
if stmt, err = NewDmStmt(dc, query); err != nil {
return
}
if err = stmt.prepare(); err != nil {
stmt.close()
stmt = nil
return
}
return
}
func (dc *DmConnection) prepareContext(ctx context.Context, query string) (*DmStatement, error) {
if err := dc.watchCancel(ctx); err != nil {
return nil, err
}
defer dc.finish()
return dc.prepare(query)
}
func (dc *DmConnection) resetSession(ctx context.Context) error {
if err := dc.watchCancel(ctx); err != nil {
return err
}
defer dc.finish()
err := dc.checkClosed()
if err != nil {
return err
}
return nil
}
func (dc *DmConnection) checkNamedValue(nv *driver.NamedValue) error {
var err error
var cvt = converter{dc, false}
nv.Value, err = cvt.ConvertValue(nv.Value)
dc.isBatch = cvt.isBatch
return err
}
func (dc *DmConnection) driverQuery(query string) (*DmStatement, *DmRows, error) {
stmt, err := NewDmStmt(dc, query)
if err != nil {
return nil, nil, err
}
stmt.innerUsed = true
stmt.innerExec = true
info, err := dc.Access.Dm_build_503(stmt, Dm_build_789)
if err != nil {
return nil, nil, err
}
dc.lastExecInfo = info
stmt.innerExec = false
return stmt, newDmRows(newInnerRows(0, stmt, info)), nil
}
func (dc *DmConnection) getIndexOnEPGroup() int32 {
if dc.dmConnector.group == nil || dc.dmConnector.group.epList == nil {
return -1
}
for i := 0; i < len(dc.dmConnector.group.epList); i++ {
ep := dc.dmConnector.group.epList[i]
if dc.dmConnector.host == ep.host && dc.dmConnector.port == ep.port {
return int32(i)
}
}
return -1
}
func (dc *DmConnection) getServerEncoding() string {
if dc.dmConnector.charCode != "" {
return dc.dmConnector.charCode
}
return dc.serverEncoding
}
func (dc *DmConnection) lobFetchAll() bool {
return dc.dmConnector.lobMode == 2
}
func (conn *DmConnection) CompatibleOracle() bool {
return conn.dmConnector.compatibleMode == COMPATIBLE_MODE_ORACLE
}
func (conn *DmConnection) CompatibleMysql() bool {
return conn.dmConnector.compatibleMode == COMPATIBLE_MODE_MYSQL
}
func (conn *DmConnection) cancel(err error) {
conn.canceled.Set(err)
conn.close()
}
func (conn *DmConnection) finish() {
if !conn.watching || conn.finished == nil {
return
}
select {
case conn.finished <- struct{}{}:
conn.watching = false
case <-conn.closech:
}
}
func (conn *DmConnection) startWatcher() {
watcher := make(chan context.Context, 1)
conn.watcher = watcher
finished := make(chan struct{})
conn.finished = finished
go func() {
for {
var ctx context.Context
select {
case ctx = <-watcher:
case <-conn.closech:
return
}
select {
case <-ctx.Done():
conn.cancel(ctx.Err())
case <-finished:
case <-conn.closech:
return
}
}
}()
}
func (conn *DmConnection) watchCancel(ctx context.Context) error {
if conn.watching {
conn.cleanup()
return nil
}
if err := ctx.Err(); err != nil {
return err
}
if ctx.Done() == nil {
return nil
}
if conn.watcher == nil {
return nil
}
conn.watching = true
conn.watcher <- ctx
return nil
}
type noCopy struct{}
func (*noCopy) Lock() {}
type atomicBool struct {
_noCopy noCopy
value uint32
}
func (ab *atomicBool) IsSet() bool {
return atomic.LoadUint32(&ab.value) > 0
}
func (ab *atomicBool) Set(value bool) {
if value {
atomic.StoreUint32(&ab.value, 1)
} else {
atomic.StoreUint32(&ab.value, 0)
}
}
func (ab *atomicBool) TrySet(value bool) bool {
if value {
return atomic.SwapUint32(&ab.value, 1) == 0
}
return atomic.SwapUint32(&ab.value, 0) > 0
}
type atomicError struct {
_noCopy noCopy
value atomic.Value
}
func (ae *atomicError) Set(value error) {
ae.value.Store(value)
}
func (ae *atomicError) Value() error {
if v := ae.value.Load(); v != nil {
return v.(error)
}
return nil
}
+985
View File
@@ -0,0 +1,985 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"bytes"
"context"
"database/sql/driver"
"net"
"net/url"
"os"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
"sync"
"time"
"gitee.com/chunanyong/dm/util"
)
const (
TimeZoneKey = "timeZone"
EnRsCacheKey = "enRsCache"
RsCacheSizeKey = "rsCacheSize"
RsRefreshFreqKey = "rsRefreshFreq"
LoginPrimary = "loginPrimary"
LoginModeKey = "loginMode"
LoginStatusKey = "loginStatus"
LoginDscCtrlKey = "loginDscCtrl"
SwitchTimesKey = "switchTimes"
SwitchIntervalKey = "switchInterval"
EpSelectorKey = "epSelector"
PrimaryKey = "primaryKey"
KeywordsKey = "keywords"
CompressKey = "compress"
CompressIdKey = "compressId"
LoginEncryptKey = "loginEncrypt"
CommunicationEncryptKey = "communicationEncrypt"
DirectKey = "direct"
Dec2DoubleKey = "dec2double"
RwSeparateKey = "rwSeparate"
RwPercentKey = "rwPercent"
RwAutoDistributeKey = "rwAutoDistribute"
CompatibleModeKey = "compatibleMode"
CompatibleOraKey = "comOra"
CipherPathKey = "cipherPath"
DoSwitchKey = "doSwitch"
DriverReconnectKey = "driverReconnect"
ClusterKey = "cluster"
LanguageKey = "language"
DbAliveCheckFreqKey = "dbAliveCheckFreq"
RwStandbyRecoverTimeKey = "rwStandbyRecoverTime"
LogLevelKey = "logLevel"
LogDirKey = "logDir"
LogBufferPoolSizeKey = "logBufferPoolSize"
LogBufferSizeKey = "logBufferSize"
LogFlusherQueueSizeKey = "logFlusherQueueSize"
LogFlushFreqKey = "logFlushFreq"
StatEnableKey = "statEnable"
StatDirKey = "statDir"
StatFlushFreqKey = "statFlushFreq"
StatHighFreqSqlCountKey = "statHighFreqSqlCount"
StatSlowSqlCountKey = "statSlowSqlCount"
StatSqlMaxCountKey = "statSqlMaxCount"
StatSqlRemoveModeKey = "statSqlRemoveMode"
AddressRemapKey = "addressRemap"
UserRemapKey = "userRemap"
ConnectTimeoutKey = "connectTimeout"
LoginCertificateKey = "loginCertificate"
UrlKey = "url"
HostKey = "host"
PortKey = "port"
UserKey = "user"
PasswordKey = "password"
DialNameKey = "dialName"
RwStandbyKey = "rwStandby"
IsCompressKey = "isCompress"
RwHAKey = "rwHA"
RwIgnoreSqlKey = "rwIgnoreSql"
AppNameKey = "appName"
OsNameKey = "osName"
MppLocalKey = "mppLocal"
SocketTimeoutKey = "socketTimeout"
SessionTimeoutKey = "sessionTimeout"
ContinueBatchOnErrorKey = "continueBatchOnError"
BatchAllowMaxErrorsKey = "batchAllowMaxErrors"
EscapeProcessKey = "escapeProcess"
AutoCommitKey = "autoCommit"
MaxRowsKey = "maxRows"
RowPrefetchKey = "rowPrefetch"
BufPrefetchKey = "bufPrefetch"
LobModeKey = "LobMode"
StmtPoolSizeKey = "StmtPoolSize"
AlwayseAllowCommitKey = "AlwayseAllowCommit"
BatchTypeKey = "batchType"
BatchNotOnCallKey = "batchNotOnCall"
IsBdtaRSKey = "isBdtaRS"
ClobAsStringKey = "clobAsString"
SslCertPathKey = "sslCertPath"
SslKeyPathKey = "sslKeyPath"
SslFilesPathKey = "sslFilesPath"
KerberosLoginConfPathKey = "kerberosLoginConfPath"
UKeyNameKey = "uKeyName"
UKeyPinKey = "uKeyPin"
ColumnNameUpperCaseKey = "columnNameUpperCase"
ColumnNameCaseKey = "columnNameCase"
DatabaseProductNameKey = "databaseProductName"
OsAuthTypeKey = "osAuthType"
SchemaKey = "schema"
CatalogKey = "catalog"
ServerOptionKey = "serverOption"
ClobToBytesKey = "clobToBytes"
DO_SWITCH_OFF int32 = 0
DO_SWITCH_WHEN_CONN_ERROR int32 = 1
DO_SWITCH_WHEN_EP_RECOVER int32 = 2
CLUSTER_TYPE_NORMAL int32 = 0
CLUSTER_TYPE_RW int32 = 1
CLUSTER_TYPE_DW int32 = 2
CLUSTER_TYPE_DSC int32 = 3
CLUSTER_TYPE_MPP int32 = 4
EP_STATUS_OK int32 = 1
EP_STATUS_ERROR int32 = 2
LOGIN_MODE_PRIMARY_FIRST int32 = 0
LOGIN_MODE_PRIMARY_ONLY int32 = 1
LOGIN_MODE_STANDBY_ONLY int32 = 2
LOGIN_MODE_STANDBY_FIRST int32 = 3
LOGIN_MODE_NORMAL_FIRST int32 = 4
SERVER_MODE_NORMAL int32 = 0
SERVER_MODE_PRIMARY int32 = 1
SERVER_MODE_STANDBY int32 = 2
SERVER_STATUS_MOUNT int32 = 3
SERVER_STATUS_OPEN int32 = 4
SERVER_STATUS_SUSPEND int32 = 5
COMPATIBLE_MODE_ORACLE int = 1
COMPATIBLE_MODE_MYSQL int = 2
LANGUAGE_CN int = 0
LANGUAGE_EN int = 1
LANGUAGE_CNT_HK = 2
COLUMN_NAME_NATURAL_CASE = 0
COLUMN_NAME_UPPER_CASE = 1
COLUMN_NAME_LOWER_CASE = 2
RW_SEPARATE_OFF int32 = 0
RW_SEPARATE_CLIENT int32 = 1
RW_SEPARATE_EP_GROUP int32 = 2
RW_SEPARATE_DB int32 = 3
RW_SEPARATE_DB_APPLY_WAIT int32 = 4
RW_SEPARATE_USER_DEFINED int32 = 5
compressDef = Dm_build_784
compressIDDef = Dm_build_785
charCodeDef = ""
enRsCacheDef = false
rsCacheSizeDef = 20
rsRefreshFreqDef = 10
loginModeDef = LOGIN_MODE_NORMAL_FIRST
loginStatusDef = 0
loginEncryptDef = true
loginCertificateDef = ""
dec2DoubleDef = false
rwHADef = false
rwStandbyDef = false
rwSeparateDef = RW_SEPARATE_OFF
rwPercentDef = 25
rwAutoDistributeDef = true
rwStandbyRecoverTimeDef = 1000
cipherPathDef = ""
urlDef = ""
userDef = "SYSDBA"
passwordDef = "SYSDBA"
hostDef = "localhost"
portDef = DEFAULT_PORT
appNameDef = ""
mppLocalDef = false
socketTimeoutDef = 0
connectTimeoutDef = 5000
sessionTimeoutDef = 0
osAuthTypeDef = Dm_build_767
continueBatchOnErrorDef = false
escapeProcessDef = false
autoCommitDef = true
maxRowsDef = 0
rowPrefetchDef = Dm_build_768
bufPrefetchDef = 0
lobModeDef = 1
stmtPoolMaxSizeDef = 15
alwayseAllowCommitDef = true
isBdtaRSDef = false
kerberosLoginConfPathDef = ""
uKeyNameDef = ""
uKeyPinDef = ""
databaseProductNameDef = ""
caseSensitiveDef = true
compatibleModeDef = 0
)
type DmConnector struct {
filterable
mu sync.Mutex
dmDriver *DmDriver
compress int
compressID int8
newClientType bool
charCode string
enRsCache bool
rsCacheSize int
rsRefreshFreq int
loginMode int32
loginStatus int
loginDscCtrl bool
switchTimes int32
switchInterval int
epSelector int32
keyWords []string
loginEncrypt bool
loginCertificate string
dec2Double bool
rwHA bool
rwStandby bool
rwSeparate int32
rwPercent int32
rwAutoDistribute bool
rwStandbyRecoverTime int
rwIgnoreSql bool
doSwitch int32
driverReconnect bool
cluster int32
cipherPath string
url string
user string
password string
dialName string
host string
group *epGroup
port int32
appName string
osName string
mppLocal bool
socketTimeout int
connectTimeout int
sessionTimeout int
osAuthType byte
continueBatchOnError bool
batchAllowMaxErrors int32
escapeProcess bool
autoCommit bool
maxRows int
rowPrefetch int
bufPrefetch int
lobMode int
stmtPoolMaxSize int
alwayseAllowCommit bool
batchType int
batchNotOnCall bool
isBdtaRS bool
sslCertPath string
sslKeyPath string
sslFilesPath string
kerberosLoginConfPath string
uKeyName string
uKeyPin string
svcConfPath string
columnNameCase int
caseSensitive bool
compatibleMode int
localTimezone int16
schema string
catalog string
logLevel int
logDir string
logFlushFreq int
logFlushQueueSize int
logBufferSize int
statEnable bool
statDir string
statFlushFreq int
statSlowSqlCount int
statHighFreqSqlCount int
statSqlMaxCount int
statSqlRemoveMode int
serverOption []string
clobToBytes bool
}
func (c *DmConnector) init() *DmConnector {
c.compress = compressDef
c.compressID = compressIDDef
c.charCode = charCodeDef
c.enRsCache = enRsCacheDef
c.rsCacheSize = rsCacheSizeDef
c.rsRefreshFreq = rsRefreshFreqDef
c.loginMode = loginModeDef
c.loginStatus = loginStatusDef
c.loginDscCtrl = false
c.switchTimes = 1
c.switchInterval = 200
c.epSelector = 0
c.keyWords = nil
c.loginEncrypt = loginEncryptDef
c.loginCertificate = loginCertificateDef
c.dec2Double = dec2DoubleDef
c.rwHA = rwHADef
c.rwStandby = rwStandbyDef
c.rwSeparate = rwSeparateDef
c.rwPercent = rwPercentDef
c.rwAutoDistribute = rwAutoDistributeDef
c.rwStandbyRecoverTime = rwStandbyRecoverTimeDef
c.rwIgnoreSql = false
c.doSwitch = DO_SWITCH_WHEN_CONN_ERROR
c.driverReconnect = false
c.cluster = CLUSTER_TYPE_NORMAL
c.cipherPath = cipherPathDef
c.url = urlDef
c.user = userDef
c.password = passwordDef
c.host = hostDef
c.port = portDef
c.appName = appNameDef
c.osName = runtime.GOOS
c.mppLocal = mppLocalDef
c.socketTimeout = socketTimeoutDef
c.connectTimeout = connectTimeoutDef
c.sessionTimeout = sessionTimeoutDef
c.osAuthType = osAuthTypeDef
c.continueBatchOnError = continueBatchOnErrorDef
c.batchAllowMaxErrors = 0
c.escapeProcess = escapeProcessDef
c.autoCommit = autoCommitDef
c.maxRows = maxRowsDef
c.rowPrefetch = rowPrefetchDef
c.bufPrefetch = bufPrefetchDef
c.lobMode = lobModeDef
c.stmtPoolMaxSize = stmtPoolMaxSizeDef
c.alwayseAllowCommit = alwayseAllowCommitDef
c.batchType = 1
c.batchNotOnCall = false
c.isBdtaRS = isBdtaRSDef
c.kerberosLoginConfPath = kerberosLoginConfPathDef
c.uKeyName = uKeyNameDef
c.uKeyPin = uKeyPinDef
c.columnNameCase = COLUMN_NAME_NATURAL_CASE
c.caseSensitive = caseSensitiveDef
c.compatibleMode = compatibleModeDef
_, tzs := time.Now().Zone()
c.localTimezone = int16(tzs / 60)
c.idGenerator = dmConntorIDGenerator
c.logDir = LogDirDef
c.logFlushFreq = LogFlushFreqDef
c.logFlushQueueSize = LogFlushQueueSizeDef
c.logBufferSize = LogBufferSizeDef
c.statEnable = StatEnableDef
c.statDir = StatDirDef
c.statFlushFreq = StatFlushFreqDef
c.statSlowSqlCount = StatSlowSqlCountDef
c.statHighFreqSqlCount = StatHighFreqSqlCountDef
c.statSqlMaxCount = StatSqlMaxCountDef
c.statSqlRemoveMode = StatSqlRemoveModeDef
return c
}
func (c *DmConnector) setAttributes(props *Properties) error {
if props == nil || props.Len() == 0 {
return nil
}
c.url = props.GetTrimString(UrlKey, c.url)
c.host = props.GetTrimString(HostKey, c.host)
c.port = int32(props.GetInt(PortKey, int(c.port), 0, 65535))
c.user = props.GetString(UserKey, c.user)
c.password = props.GetString(PasswordKey, c.password)
c.dialName = props.GetString(DialNameKey, "")
c.rwStandby = props.GetBool(RwStandbyKey, c.rwStandby)
if b := props.GetBool(IsCompressKey, false); b {
c.compress = Dm_build_783
}
c.compress = props.GetInt(CompressKey, c.compress, 0, 2)
c.compressID = int8(props.GetInt(CompressIdKey, int(c.compressID), 0, 1))
c.enRsCache = props.GetBool(EnRsCacheKey, c.enRsCache)
c.localTimezone = int16(props.GetInt(TimeZoneKey, int(c.localTimezone), -779, 840))
c.rsCacheSize = props.GetInt(RsCacheSizeKey, c.rsCacheSize, 0, int(INT32_MAX))
c.rsRefreshFreq = props.GetInt(RsRefreshFreqKey, c.rsRefreshFreq, 0, int(INT32_MAX))
c.loginMode = int32(props.GetInt(LoginModeKey, int(c.loginMode), 0, 4))
c.loginStatus = props.GetInt(LoginStatusKey, c.loginStatus, 0, int(INT32_MAX))
c.loginDscCtrl = props.GetBool(LoginDscCtrlKey, c.loginDscCtrl)
c.switchTimes = int32(props.GetInt(SwitchTimesKey, int(c.switchTimes), 0, int(INT32_MAX)))
c.switchInterval = props.GetInt(SwitchIntervalKey, c.switchInterval, 0, int(INT32_MAX))
c.epSelector = int32(props.GetInt(EpSelectorKey, int(c.epSelector), 0, 1))
c.loginEncrypt = props.GetBool(LoginEncryptKey, c.loginEncrypt)
c.loginCertificate = props.GetTrimString(LoginCertificateKey, c.loginCertificate)
c.dec2Double = props.GetBool(Dec2DoubleKey, c.dec2Double)
parseLanguage(props.GetString(LanguageKey, ""))
c.rwSeparate = int32(props.GetInt(RwSeparateKey, int(c.rwSeparate), 0, 4))
c.rwAutoDistribute = props.GetBool(RwAutoDistributeKey, c.rwAutoDistribute)
c.rwPercent = int32(props.GetInt(RwPercentKey, int(c.rwPercent), 0, 100))
c.rwHA = props.GetBool(RwHAKey, c.rwHA)
c.rwStandbyRecoverTime = props.GetInt(RwStandbyRecoverTimeKey, c.rwStandbyRecoverTime, 0, int(INT32_MAX))
c.rwIgnoreSql = props.GetBool(RwIgnoreSqlKey, c.rwIgnoreSql)
c.doSwitch = int32(props.GetInt(DoSwitchKey, int(c.doSwitch), 0, 2))
c.driverReconnect = props.GetBool(DriverReconnectKey, c.driverReconnect)
c.parseCluster(props)
c.cipherPath = props.GetTrimString(CipherPathKey, c.cipherPath)
if props.GetBool(CompatibleOraKey, false) {
c.compatibleMode = int(COMPATIBLE_MODE_ORACLE)
}
c.parseCompatibleMode(props)
c.keyWords = props.GetStringArray(KeywordsKey, c.keyWords)
c.appName = props.GetTrimString(AppNameKey, c.appName)
c.osName = props.GetTrimString(OsNameKey, c.osName)
c.mppLocal = props.GetBool(MppLocalKey, c.mppLocal)
c.socketTimeout = props.GetInt(SocketTimeoutKey, c.socketTimeout, 0, int(INT32_MAX))
c.connectTimeout = props.GetInt(ConnectTimeoutKey, c.connectTimeout, 0, int(INT32_MAX))
c.sessionTimeout = props.GetInt(SessionTimeoutKey, c.sessionTimeout, 0, int(INT32_MAX))
err := c.parseOsAuthType(props)
if err != nil {
return err
}
c.continueBatchOnError = props.GetBool(ContinueBatchOnErrorKey, c.continueBatchOnError)
c.batchAllowMaxErrors = int32(props.GetInt(BatchAllowMaxErrorsKey, int(c.batchAllowMaxErrors), 0, int(INT32_MAX)))
c.escapeProcess = props.GetBool(EscapeProcessKey, c.escapeProcess)
c.autoCommit = props.GetBool(AutoCommitKey, c.autoCommit)
c.maxRows = props.GetInt(MaxRowsKey, c.maxRows, 0, int(INT32_MAX))
c.rowPrefetch = props.GetInt(RowPrefetchKey, c.rowPrefetch, 0, int(INT32_MAX))
c.bufPrefetch = props.GetInt(BufPrefetchKey, c.bufPrefetch, int(Dm_build_769), int(Dm_build_770))
c.lobMode = props.GetInt(LobModeKey, c.lobMode, 1, 2)
c.stmtPoolMaxSize = props.GetInt(StmtPoolSizeKey, c.stmtPoolMaxSize, 0, int(INT32_MAX))
c.alwayseAllowCommit = props.GetBool(AlwayseAllowCommitKey, c.alwayseAllowCommit)
c.batchType = props.GetInt(BatchTypeKey, c.batchType, 1, 2)
c.batchNotOnCall = props.GetBool(BatchNotOnCallKey, c.batchNotOnCall)
c.isBdtaRS = props.GetBool(IsBdtaRSKey, c.isBdtaRS)
c.sslFilesPath = props.GetTrimString(SslFilesPathKey, c.sslFilesPath)
c.sslCertPath = props.GetTrimString(SslCertPathKey, c.sslCertPath)
if c.sslCertPath == "" && c.sslFilesPath != "" {
c.sslCertPath = filepath.Join(c.sslFilesPath, "client-cert.pem")
}
c.sslKeyPath = props.GetTrimString(SslKeyPathKey, c.sslKeyPath)
if c.sslKeyPath == "" && c.sslFilesPath != "" {
c.sslKeyPath = filepath.Join(c.sslKeyPath, "client-key.pem")
}
c.kerberosLoginConfPath = props.GetTrimString(KerberosLoginConfPathKey, c.kerberosLoginConfPath)
c.uKeyName = props.GetTrimString(UKeyNameKey, c.uKeyName)
c.uKeyPin = props.GetTrimString(UKeyPinKey, c.uKeyPin)
c.svcConfPath = props.GetString("confPath", "")
if props.GetBool(ColumnNameUpperCaseKey, false) {
c.columnNameCase = COLUMN_NAME_UPPER_CASE
}
v := props.GetTrimString(ColumnNameCaseKey, "")
if util.StringUtil.EqualsIgnoreCase(v, "upper") {
c.columnNameCase = COLUMN_NAME_UPPER_CASE
} else if util.StringUtil.EqualsIgnoreCase(v, "lower") {
c.columnNameCase = COLUMN_NAME_LOWER_CASE
}
c.schema = props.GetTrimString(SchemaKey, c.schema)
c.catalog = props.GetTrimString(CatalogKey, c.catalog)
c.logLevel = ParseLogLevel(props)
LogLevel = c.logLevel
c.logDir = util.StringUtil.FormatDir(props.GetTrimString(LogDirKey, LogDirDef))
LogDir = c.logDir
c.logBufferSize = props.GetInt(LogBufferSizeKey, LogBufferSizeDef, 1, int(INT32_MAX))
LogBufferSize = c.logBufferSize
c.logFlushFreq = props.GetInt(LogFlushFreqKey, LogFlushFreqDef, 1, int(INT32_MAX))
LogFlushFreq = c.logFlushFreq
c.logFlushQueueSize = props.GetInt(LogFlusherQueueSizeKey, LogFlushQueueSizeDef, 1, int(INT32_MAX))
LogFlushQueueSize = c.logFlushQueueSize
c.statEnable = props.GetBool(StatEnableKey, StatEnableDef)
StatEnable = c.statEnable
c.statDir = util.StringUtil.FormatDir(props.GetTrimString(StatDirKey, StatDirDef))
StatDir = c.statDir
c.statFlushFreq = props.GetInt(StatFlushFreqKey, StatFlushFreqDef, 1, int(INT32_MAX))
StatFlushFreq = c.statFlushFreq
c.statHighFreqSqlCount = props.GetInt(StatHighFreqSqlCountKey, StatHighFreqSqlCountDef, 0, 1000)
StatHighFreqSqlCount = c.statHighFreqSqlCount
c.statSlowSqlCount = props.GetInt(StatSlowSqlCountKey, StatSlowSqlCountDef, 0, 1000)
StatSlowSqlCount = c.statSlowSqlCount
c.statSqlMaxCount = props.GetInt(StatSqlMaxCountKey, StatSqlMaxCountDef, 0, 100000)
StatSqlMaxCount = c.statSqlMaxCount
c.parseStatSqlRemoveMode(props)
c.parseServerOption(props)
c.clobToBytes = props.GetBool(ClobToBytesKey, ClobToBytesDef)
return nil
}
func (c *DmConnector) parseServerOption(props *Properties) {
value := props.GetString(ServerOptionKey, "")
if len(value) == 0 {
return
}
if strings.HasPrefix(value, "{") && strings.HasSuffix(value, "}") {
value = strings.TrimPrefix(value, "{")
value = strings.TrimSuffix(value, "}")
}
c.serverOption = strings.Split(value, ",")
}
func (c *DmConnector) parseOsAuthType(props *Properties) error {
value := props.GetString(OsAuthTypeKey, "")
if value != "" && !util.StringUtil.IsDigit(value) {
if util.StringUtil.EqualsIgnoreCase(value, "ON") {
c.osAuthType = Dm_build_767
} else if util.StringUtil.EqualsIgnoreCase(value, "SYSDBA") {
c.osAuthType = Dm_build_763
} else if util.StringUtil.EqualsIgnoreCase(value, "SYSAUDITOR") {
c.osAuthType = Dm_build_765
} else if util.StringUtil.EqualsIgnoreCase(value, "SYSSSO") {
c.osAuthType = Dm_build_764
} else if util.StringUtil.EqualsIgnoreCase(value, "AUTO") {
c.osAuthType = Dm_build_766
} else if util.StringUtil.EqualsIgnoreCase(value, "OFF") {
c.osAuthType = Dm_build_762
}
} else {
c.osAuthType = byte(props.GetInt(OsAuthTypeKey, int(c.osAuthType), 0, 4))
}
if c.user == "" && c.osAuthType == Dm_build_762 {
c.user = "SYSDBA"
} else if c.osAuthType != Dm_build_762 && c.user != "" {
return ECGO_OSAUTH_ERROR.throw()
} else if c.osAuthType != Dm_build_762 {
c.user = os.Getenv("user")
c.password = ""
}
return nil
}
func (c *DmConnector) parseCompatibleMode(props *Properties) {
value := props.GetString(CompatibleModeKey, "")
if value != "" && !util.StringUtil.IsDigit(value) {
if util.StringUtil.EqualsIgnoreCase(value, "oracle") {
c.compatibleMode = COMPATIBLE_MODE_ORACLE
} else if util.StringUtil.EqualsIgnoreCase(value, "mysql") {
c.compatibleMode = COMPATIBLE_MODE_MYSQL
}
} else {
c.compatibleMode = props.GetInt(CompatibleModeKey, c.compatibleMode, 0, 2)
}
}
func (c *DmConnector) parseStatSqlRemoveMode(props *Properties) {
value := props.GetString(StatSqlRemoveModeKey, "")
if value != "" && !util.StringUtil.IsDigit(value) {
if util.StringUtil.EqualsIgnoreCase("oldest", value) || util.StringUtil.EqualsIgnoreCase("eldest", value) {
c.statSqlRemoveMode = STAT_SQL_REMOVE_OLDEST
} else if util.StringUtil.EqualsIgnoreCase("latest", value) {
c.statSqlRemoveMode = STAT_SQL_REMOVE_LATEST
}
} else {
c.statSqlRemoveMode = props.GetInt(StatSqlRemoveModeKey, StatSqlRemoveModeDef, 1, 2)
}
}
func (c *DmConnector) parseCluster(props *Properties) {
value := props.GetTrimString(ClusterKey, "")
if util.StringUtil.EqualsIgnoreCase(value, "DSC") {
c.cluster = CLUSTER_TYPE_DSC
} else if util.StringUtil.EqualsIgnoreCase(value, "RW") {
c.cluster = CLUSTER_TYPE_RW
} else if util.StringUtil.EqualsIgnoreCase(value, "DW") {
c.cluster = CLUSTER_TYPE_DW
} else if util.StringUtil.EqualsIgnoreCase(value, "MPP") {
c.cluster = CLUSTER_TYPE_MPP
} else {
c.cluster = CLUSTER_TYPE_NORMAL
}
}
func (c *DmConnector) parseDSN(dsn string) (*Properties, string, string, error) {
var dsnProps = NewProperties()
if strings.Index(dsn, "dm://") != 0 {
return nil, "", "", DSN_INVALID_SCHEMA
}
dsn = dsn[5:]
urlString := dsn
queryIndex := strings.LastIndex(dsn, "?")
if queryIndex > 0 {
urlString = dsn[:queryIndex]
var queryString = dsn[queryIndex+1:]
for _, kvString := range strings.Split(queryString, "&") {
kv := strings.SplitN(kvString, "=", 2)
if kv != nil && len(kv) > 1 {
dsnProps.Set(kv[0], kv[1])
}
}
}
hostString := urlString
atIndex := strings.LastIndex(urlString, "@")
if atIndex == -1 {
return nil, "", "", DSN_INVALID_FORMAT
} else {
var userString = urlString[:atIndex]
hostString = urlString[atIndex+1:]
kv := strings.SplitN(userString, ":", 2)
if kv != nil && len(kv) > 1 {
c.user = kv[0]
c.password = kv[1]
}
}
if catalogIndex := strings.LastIndex(hostString, "/"); catalogIndex > 0 {
return dsnProps, hostString[0:catalogIndex], hostString[catalogIndex+1:], nil
}
return dsnProps, hostString, "", nil
}
func (c *DmConnector) BuildDSN() string {
var buf bytes.Buffer
buf.WriteString("dm://")
if len(c.user) > 0 {
buf.WriteString(url.QueryEscape(c.user))
if len(c.password) > 0 {
buf.WriteByte(':')
buf.WriteString(url.QueryEscape(c.password))
}
buf.WriteByte('@')
}
if len(c.host) > 0 {
buf.WriteString(c.host)
if c.port > 0 {
buf.WriteByte(':')
buf.WriteString(strconv.Itoa(int(c.port)))
}
}
hasParam := false
if c.connectTimeout > 0 {
if hasParam {
buf.WriteString("&timeout=")
} else {
buf.WriteString("?timeout=")
hasParam = true
}
buf.WriteString(strconv.Itoa(c.connectTimeout))
}
return buf.String()
}
func (c *DmConnector) mergeConfigs(dsn string) error {
props, host, catalog, err := c.parseDSN(dsn)
if err != nil {
return err
}
driverInit(props.GetString("svcConfPath", ""))
addressRemapStr := props.GetTrimString(AddressRemapKey, "")
userRemapStr := props.GetTrimString(UserRemapKey, "")
if addressRemapStr == "" {
addressRemapStr = GlobalProperties.GetTrimString(AddressRemapKey, "")
}
if userRemapStr == "" {
userRemapStr = GlobalProperties.GetTrimString(UserRemapKey, "")
}
host = c.remap(host, addressRemapStr)
c.user = c.remap(c.user, userRemapStr)
if a := props.GetTrimString(host, ""); a != "" {
if strings.HasPrefix(a, "(") && strings.HasSuffix(a, ")") {
a = strings.TrimSpace(a[1 : len(a)-1])
}
c.group = parseServerName(host, a)
if c.group != nil {
c.group.props = NewProperties()
c.group.props.SetProperties(GlobalProperties)
}
} else if group, ok := ServerGroupMap.Load(strings.ToLower(host)); ok {
c.group = group.(*epGroup)
} else {
host, port, err := net.SplitHostPort(host)
if err == nil {
ip := net.ParseIP(host)
var v4InV6Prefix = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}
if ip != nil && len(ip) == net.IPv6len && !bytes.Equal(ip[0:12], v4InV6Prefix) {
host = "[" + host + "]"
}
}
c.host = host
tmpPort, err := strconv.Atoi(port)
if err != nil {
c.port = portDef
} else {
c.port = int32(tmpPort)
}
if len(catalog) > 0 {
c.schema = catalog
}
c.group = newEPGroup(c.host+":"+strconv.Itoa(int(c.port)), []*ep{newEP(c.host, c.port)})
}
props.SetDiffProperties(c.group.props)
props.SetDiffProperties(GlobalProperties)
if c.rwSeparate = int32(props.GetInt(RwSeparateKey, 0, 0, 5)); c.rwSeparate > RW_SEPARATE_OFF {
props.SetIfNotExist(LoginModeKey, strconv.Itoa(int(LOGIN_MODE_PRIMARY_ONLY)))
props.SetIfNotExist(LoginStatusKey, strconv.Itoa(int(SERVER_STATUS_OPEN)))
props.SetIfNotExist(DoSwitchKey, "true")
}
if err = c.setAttributes(props); err != nil {
return err
}
return nil
}
func (c *DmConnector) remap(origin string, cfgStr string) string {
if cfgStr == "" || origin == "" {
return origin
}
maps := regexp.MustCompile("\\(.*?,.*?\\)").FindAllString(cfgStr, -1)
for _, kvStr := range maps {
kv := strings.Split(strings.TrimSpace(kvStr[1:len(kvStr)-1]), ",")
if util.StringUtil.Equals(strings.TrimSpace(kv[0]), origin) {
return strings.TrimSpace(kv[1])
}
}
return origin
}
func (c *DmConnector) Connect(ctx context.Context) (driver.Conn, error) {
c.mu.Lock()
defer c.mu.Unlock()
return c.filterChain.reset().DmConnectorConnect(c, ctx)
}
func (c *DmConnector) Driver() driver.Driver {
c.mu.Lock()
defer c.mu.Unlock()
return c.filterChain.reset().DmConnectorDriver(c)
}
func (c *DmConnector) connect(ctx context.Context) (*DmConnection, error) {
if c.group != nil && len(c.group.epList) > 0 {
return c.group.connect(c)
} else {
return c.connectSingle(ctx)
}
}
func (c *DmConnector) driver() *DmDriver {
return c.dmDriver
}
func (c *DmConnector) connectSingle(ctx context.Context) (*DmConnection, error) {
var err error
var dc = &DmConnection{
closech: make(chan struct{}),
dmConnector: c,
autoCommit: c.autoCommit,
}
dc.createFilterChain(c, nil)
dc.objId = -1
dc.init()
dc.Access, err = dm_build_426(ctx, dc)
if err != nil {
return nil, err
}
dc.startWatcher()
if err = dc.watchCancel(ctx); err != nil {
return nil, err
}
defer dc.finish()
if err = dc.Access.dm_build_471(); err != nil {
if !dc.closed.IsSet() {
close(dc.closech)
if dc.Access != nil {
dc.Access.Close()
}
dc.closed.Set(true)
}
return nil, err
}
if c.schema != "" {
_, err = dc.exec("set schema \""+util.StringUtil.ProcessDoubleQuoteOfName(c.schema)+"\"", nil)
if err != nil {
dc.cleanup()
return nil, err
}
}
return dc, nil
}
+456
View File
@@ -0,0 +1,456 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"database/sql/driver"
"math/big"
"reflect"
"strconv"
"strings"
)
const (
XDEC_MAX_PREC int = 40
XDEC_SIZE = 21
FLAG_ZERO int = 0x80
FLAG_POSITIVE int = 0xC1
FLAG_NEGTIVE int = 0x3E
POSITIVE_EXP_MAX = 0xff - FLAG_POSITIVE
EXP_MAX int = 0xFF - 1 - FLAG_POSITIVE
EXP_MIN int = FLAG_NEGTIVE + 1 - 0x7F
NUM_POSITIVE int = 1
NUM_NEGTIVE int = 101
)
type DmDecimal struct {
sign int
weight int
prec int
scale int
digits string
Valid bool
}
func NewDecimalFromInt64(x int64) (*DmDecimal, error) {
return NewDecimalFromBigInt(big.NewInt(x))
}
func (d DmDecimal) ToInt64() int64 {
return d.ToBigInt().Int64()
}
func NewDecimalFromFloat64(x float64) (*DmDecimal, error) {
return NewDecimalFromBigFloat(big.NewFloat(x))
}
func (d DmDecimal) ToFloat64() float64 {
f, _ := d.ToBigFloat().Float64()
return f
}
func NewDecimalFromBigInt(bigInt *big.Int) (*DmDecimal, error) {
return newDecimal(bigInt, len(bigInt.String()), 0)
}
func (d DmDecimal) ToBigInt() *big.Int {
if d.isZero() {
return big.NewInt(0)
}
var digits = d.digits
if d.sign < 0 {
digits = "-" + digits
}
i1, ok := new(big.Int).SetString(digits, 10)
if !ok {
return nil
}
if d.weight > 0 {
i2, ok := new(big.Int).SetString("1"+strings.Repeat("0", d.weight), 10)
if !ok {
return nil
}
i1.Mul(i1, i2)
} else if d.weight < 0 {
i2, ok := new(big.Int).SetString("1"+strings.Repeat("0", -d.weight), 10)
if !ok {
return nil
}
i1.Quo(i1, i2)
}
return i1
}
func NewDecimalFromBigFloat(bigFloat *big.Float) (*DmDecimal, error) {
return newDecimal(bigFloat, int(bigFloat.Prec()), int(bigFloat.Prec()))
}
func (d DmDecimal) ToBigFloat() *big.Float {
if d.isZero() {
return big.NewFloat(0.0)
}
var digits = d.digits
if d.sign < 0 {
digits = "-" + digits
}
f1, ok := new(big.Float).SetString(digits)
if !ok {
return nil
}
if d.weight > 0 {
f2, ok := new(big.Float).SetString("1" + strings.Repeat("0", d.weight))
if !ok {
return nil
}
f1.Mul(f1, f2)
} else if d.weight < 0 {
f2, ok := new(big.Float).SetString("1" + strings.Repeat("0", -d.weight))
if !ok {
return nil
}
f1.Quo(f1, f2)
}
return f1
}
func NewDecimalFromString(s string) (*DmDecimal, error) {
num, ok := new(big.Float).SetString(strings.TrimSpace(s))
if !ok {
return nil, ECGO_DATA_CONVERTION_ERROR.throw()
}
return NewDecimalFromBigFloat(num)
}
func (d DmDecimal) String() string {
if d.isZero() {
return "0"
}
digitsStr := d.digits
if d.weight > 0 {
digitsStr = digitsStr + strings.Repeat("0", d.weight)
} else if d.weight < 0 {
if len(digitsStr) < -d.weight {
digitsStr = strings.Repeat("0", -d.weight-len(digitsStr)+1) + digitsStr
}
indexOfDot := len(digitsStr) + d.weight
digitsStr = digitsStr[:indexOfDot] + "." + digitsStr[indexOfDot:]
}
if digitsStr[0] == '0' && digitsStr[1] != '.' {
digitsStr = digitsStr[1:]
}
if digitsStr[len(digitsStr)-1] == '0' && strings.IndexRune(digitsStr, '.') >= 0 {
digitsStr = digitsStr[0 : len(digitsStr)-1]
}
if d.sign < 0 {
digitsStr = "-" + digitsStr
}
return digitsStr
}
func (d DmDecimal) Sign() int {
return d.sign
}
func (dest *DmDecimal) Scan(src interface{}) error {
if dest == nil {
return ECGO_STORE_IN_NIL_POINTER.throw()
}
switch src := src.(type) {
case nil:
*dest = *new(DmDecimal)
(*dest).Valid = false
return nil
case int, int8, int16, int32, int64:
d, err := NewDecimalFromInt64(reflect.ValueOf(src).Int())
if err != nil {
return err
}
*dest = *d
return nil
case uint, uint8, uint16, uint32, uint64:
d, err := NewDecimalFromBigInt(new(big.Int).SetUint64(reflect.ValueOf(src).Uint()))
if err != nil {
return err
}
*dest = *d
return nil
case float32, float64:
d, err := NewDecimalFromFloat64(reflect.ValueOf(src).Float())
if err != nil {
return err
}
*dest = *d
return nil
case string:
d, err := NewDecimalFromString(src)
if err != nil {
return err
}
*dest = *d
return nil
case *DmDecimal:
*dest = *src
return nil
default:
return UNSUPPORTED_SCAN
}
}
func (d DmDecimal) Value() (driver.Value, error) {
if !d.Valid {
return nil, nil
}
return d, nil
}
func newDecimal(dec interface{}, prec int, scale int) (*DmDecimal, error) {
d := &DmDecimal{
prec: prec,
scale: scale,
Valid: true,
}
if isFloat(DECIMAL, scale) {
d.prec = getFloatPrec(prec)
d.scale = -1
}
switch de := dec.(type) {
case *big.Int:
d.sign = de.Sign()
if d.isZero() {
return d, nil
}
str := de.String()
if d.sign < 0 {
str = str[1:]
}
if err := checkPrec(len(str), prec); err != nil {
return d, err
}
i := 0
istart := len(str) - 1
for i = istart; i > 0; i-- {
if str[i] != '0' {
break
}
}
str = str[:i+1]
d.weight += istart - i
if isOdd(d.weight) {
str += "0"
d.weight -= 1
}
if isOdd(len(str)) {
str = "0" + str
}
d.digits = str
case *big.Float:
d.sign = de.Sign()
if d.isZero() {
return d, nil
}
str := de.Text('f', -1)
if d.sign < 0 {
str = str[1:]
}
pointIndex := strings.IndexByte(str, '.')
i, istart, length := 0, 0, len(str)
if pointIndex != -1 {
if str[0] == '0' {
istart = 2
for i = istart; i < length; i++ {
if str[i] != '0' {
break
}
}
str = str[i:]
d.weight -= i - istart + len(str)
} else {
str = str[:pointIndex] + str[pointIndex+1:]
d.weight -= length - pointIndex - 1
}
}
length = len(str)
istart = length - 1
for i = istart; i > 0; i-- {
if str[i] != '0' {
break
}
}
str = str[:i+1] + str[length:]
d.weight += istart - i
if isOdd(d.weight) {
str += "0"
d.weight -= 1
}
if isOdd(len(str)) {
str = "0" + str
}
d.digits = str
case []byte:
return decodeDecimal(de, prec, scale)
}
return d, nil
}
func (d DmDecimal) encodeDecimal() ([]byte, error) {
if d.isZero() {
return []byte{byte(FLAG_ZERO)}, nil
}
exp := (d.weight+len(d.digits))/2 - 1
var realExpMax int
if d.sign == NUM_POSITIVE {
realExpMax = POSITIVE_EXP_MAX
} else {
realExpMax = EXP_MAX
}
if exp > realExpMax || exp < EXP_MIN {
return nil, ECGO_DATA_TOO_LONG.throw()
}
validLen := len(d.digits)/2 + 1
if d.sign < 0 && validLen >= XDEC_SIZE {
validLen = XDEC_SIZE - 1
} else if validLen > XDEC_SIZE {
validLen = XDEC_SIZE
}
retLen := validLen
if d.sign < 0 {
retLen = validLen + 1
}
retBytes := make([]byte, retLen)
if d.sign > 0 {
retBytes[0] = byte(exp + FLAG_POSITIVE)
} else {
retBytes[0] = byte(FLAG_NEGTIVE - exp)
}
ibytes := 1
for ichar := 0; ibytes < validLen; {
digit1, err := strconv.Atoi(string(d.digits[ichar]))
if err != nil {
return nil, err
}
ichar++
digit2, err := strconv.Atoi(string(d.digits[ichar]))
ichar++
if err != nil {
return nil, err
}
digit := digit1*10 + digit2
if d.sign > 0 {
retBytes[ibytes] = byte(digit + NUM_POSITIVE)
} else {
retBytes[ibytes] = byte(NUM_NEGTIVE - digit)
}
ibytes++
}
if d.sign < 0 && ibytes < retLen {
retBytes[ibytes] = 0x66
ibytes++
}
if ibytes < retLen {
retBytes[ibytes] = 0x00
}
return retBytes, nil
}
func decodeDecimal(values []byte, prec int, scale int) (*DmDecimal, error) {
var decimal = &DmDecimal{
prec: prec,
scale: scale,
sign: 0,
weight: 0,
Valid: true,
}
if values == nil || len(values) == 0 || len(values) > XDEC_SIZE {
return nil, ECGO_FATAL_ERROR.throw()
}
if values[0] == byte(FLAG_ZERO) || len(values) == 1 {
return decimal, nil
}
if values[0]&byte(FLAG_ZERO) != 0 {
decimal.sign = 1
} else {
decimal.sign = -1
}
var flag = int(Dm_build_1346.Dm_build_1466(values, 0))
var exp int
if decimal.sign > 0 {
exp = flag - FLAG_POSITIVE
} else {
exp = FLAG_NEGTIVE - flag
}
var digit = 0
var sf = ""
for ival := 1; ival < len(values); ival++ {
if decimal.sign > 0 {
digit = int(values[ival]) - NUM_POSITIVE
} else {
digit = NUM_NEGTIVE - int(values[ival])
}
if digit < 0 || digit > 99 {
break
}
if digit < 10 {
sf += "0"
}
sf += strconv.Itoa(digit)
}
decimal.digits = sf
decimal.weight = exp*2 - (len(decimal.digits) - 2)
return decimal, nil
}
func (d DmDecimal) isZero() bool {
return d.sign == 0
}
func checkPrec(len int, prec int) error {
if prec > 0 && len > prec || len > XDEC_MAX_PREC {
return ECGO_DATA_TOO_LONG.throw()
}
return nil
}
func isOdd(val int) bool {
return val%2 != 0
}
func (d *DmDecimal) checkValid() error {
if !d.Valid {
return ECGO_IS_NULL.throw()
}
return nil
}
func (d *DmDecimal) GormDataType() string {
return "DECIMAL"
}
+119
View File
@@ -0,0 +1,119 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"context"
"database/sql"
"database/sql/driver"
"net"
"sync"
"gitee.com/chunanyong/dm/i18n"
)
// 发版标记
var version = "8.1.4.170"
var build_date = "2025.11.21"
var svn = "43114"
var globalDmDriver = newDmDriver()
func init() {
sql.Register("dm", globalDmDriver)
i18n.InitConfig(i18n.Messages_zh_CN)
i18n.InitConfig(i18n.Messages_en_US)
i18n.InitConfig(i18n.Messages_zh_HK)
}
func driverInit(svcConfPath string) {
load(svcConfPath)
if GlobalProperties != nil && GlobalProperties.Len() > 0 {
setDriverAttributes(GlobalProperties)
}
globalDmDriver.createFilterChain(nil, GlobalProperties)
}
type DmDriver struct {
filterable
mu sync.Mutex
//readPropMutex sync.Mutex
}
func newDmDriver() *DmDriver {
d := new(DmDriver)
d.idGenerator = dmDriverIDGenerator
return d
}
// 支持自定义连接网络地址,返回标准net.Conn对象,相关数据库操作的消息包都将发送到该对象
type DialFunc func(addr string) (net.Conn, error)
// 支持自定义连接网络地址,返回标准net.Conn对象,相关数据库操作的消息包都将发送到该对象
type DialContextFunc func(ctx context.Context, addr string) (net.Conn, error)
var (
dialsLock sync.RWMutex
dials map[string]DialContextFunc
)
// 注册自定义连接方法
func RegisterDial(dialName string, dial DialFunc) {
RegisterDialContext(dialName, func(_ context.Context, addr string) (net.Conn, error) {
return dial(addr)
})
}
// 注册自定义连接方法
func RegisterDialContext(dialName string, dial DialContextFunc) {
dialsLock.Lock()
defer dialsLock.Unlock()
if dials == nil {
dials = make(map[string]DialContextFunc)
}
dials[dialName] = dial
}
/*************************************************************
** PUBLIC METHODS AND FUNCTIONS
*************************************************************/
func (d *DmDriver) Open(dsn string) (driver.Conn, error) {
d.mu.Lock()
defer d.mu.Unlock()
return d.open(dsn)
}
func (d *DmDriver) OpenConnector(dsn string) (driver.Connector, error) {
d.mu.Lock()
defer d.mu.Unlock()
return d.openConnector(dsn)
}
func (d *DmDriver) open(dsn string) (*DmConnection, error) {
c, err := d.openConnector(dsn)
if err != nil {
return nil, err
}
return c.connect(context.Background())
}
func (d *DmDriver) openConnector(dsn string) (*DmConnector, error) {
connector := new(DmConnector).init()
connector.url = dsn
connector.dmDriver = d
//d.readPropMutex.Lock()
err := connector.mergeConfigs(dsn)
//d.readPropMutex.Unlock()
if err != nil {
return nil, err
}
connector.createFilterChain(connector, nil)
return connector, nil
}
func GetDriverVersion() string {
return version
}
+46
View File
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package parser
import "strconv"
const (
MAX_DEC_LEN = 38
)
const (
NORMAL int = iota
INT
DOUBLE
DECIMAL
STRING
HEX_INT
WHITESPACE_OR_COMMENT
NULL
)
type LVal struct {
Value string
Tp int
Position int
}
func newLValNoParams() *LVal {
return new(LVal).reset()
}
func newLVal(value string, tp int) *LVal {
return &LVal{Value: value, Tp: tp}
}
func (l *LVal) reset() *LVal {
l.Value = ""
l.Tp = NORMAL
return l
}
func (l *LVal) String() string {
return strconv.Itoa(l.Tp) + ":" + l.Value
}
+1206
View File
File diff suppressed because it is too large Load Diff
+1455
View File
File diff suppressed because it is too large Load Diff
+494
View File
@@ -0,0 +1,494 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"database/sql/driver"
"math"
"strconv"
"strings"
"gitee.com/chunanyong/dm/util"
)
const (
QUA_Y = 0
QUA_YM = 1
QUA_MO = 2
)
type DmIntervalYM struct {
leadScale int
isLeadScaleSet bool
_type byte
years int
months int
scaleForSvr int
Valid bool
}
func newDmIntervalYM() *DmIntervalYM {
return &DmIntervalYM{
Valid: true,
}
}
func NewDmIntervalYMByString(str string) (ym *DmIntervalYM, err error) {
defer func() {
if p := recover(); p != nil {
err = ECGO_INVALID_TIME_INTERVAL.throw()
}
}()
ym = newDmIntervalYM()
ym.isLeadScaleSet = false
if err = ym.parseIntervYMString(strings.TrimSpace(str)); err != nil {
return nil, err
}
return ym, nil
}
func newDmIntervalYMByBytes(bytes []byte) *DmIntervalYM {
ym := newDmIntervalYM()
ym.scaleForSvr = int(Dm_build_1346.Dm_build_1448(bytes, 8))
ym.leadScale = (ym.scaleForSvr >> 4) & 0x0000000F
ym._type = bytes[9]
switch ym._type {
case QUA_Y:
ym.years = int(Dm_build_1346.Dm_build_1448(bytes, 0))
case QUA_YM:
ym.years = int(Dm_build_1346.Dm_build_1448(bytes, 0))
ym.months = int(Dm_build_1346.Dm_build_1448(bytes, 4))
case QUA_MO:
ym.months = int(Dm_build_1346.Dm_build_1448(bytes, 4))
}
return ym
}
func (ym *DmIntervalYM) GetYear() int {
return ym.years
}
func (ym *DmIntervalYM) GetMonth() int {
return ym.months
}
func (ym *DmIntervalYM) GetYMType() byte {
return ym._type
}
func (ym *DmIntervalYM) String() string {
if !ym.Valid {
return ""
}
str := "INTERVAL "
var year, month string
var l int
var destLen int
switch ym._type {
case QUA_Y:
year = strconv.FormatInt(int64(math.Abs(float64(ym.years))), 10)
if ym.years < 0 {
str += "-"
}
if ym.leadScale > len(year) {
l = len(year)
destLen = ym.leadScale
for destLen > l {
year = "0" + year
destLen--
}
}
str += "'" + year + "' YEAR(" + strconv.FormatInt(int64(ym.leadScale), 10) + ")"
case QUA_YM:
year = strconv.FormatInt(int64(math.Abs(float64(ym.years))), 10)
month = strconv.FormatInt(int64(math.Abs(float64(ym.months))), 10)
if ym.years < 0 || ym.months < 0 {
str += "-"
}
if ym.leadScale > len(year) {
l = len(year)
destLen = ym.leadScale
for destLen > l {
year = "0" + year
destLen--
}
}
if len(month) < 2 {
month = "0" + month
}
str += "'" + year + "-" + month + "' YEAR(" + strconv.FormatInt(int64(ym.leadScale), 10) + ") TO MONTH"
case QUA_MO:
month = strconv.FormatInt(int64(math.Abs(float64(ym.months))), 10)
if ym.months < 0 {
str += "-"
}
if ym.leadScale > len(month) {
l = len(month)
destLen = ym.leadScale
for destLen > l {
month = "0" + month
destLen--
}
}
str += "'" + month + "' MONTH(" + strconv.FormatInt(int64(ym.leadScale), 10) + ")"
}
return str
}
func (dest *DmIntervalYM) Scan(src interface{}) error {
if dest == nil {
return ECGO_STORE_IN_NIL_POINTER.throw()
}
switch src := src.(type) {
case nil:
*dest = *new(DmIntervalYM)
(*dest).Valid = false
return nil
case *DmIntervalYM:
*dest = *src
return nil
case string:
ret, err := NewDmIntervalYMByString(src)
if err != nil {
return err
}
*dest = *ret
return nil
default:
return UNSUPPORTED_SCAN
}
}
func (ym DmIntervalYM) Value() (driver.Value, error) {
if !ym.Valid {
return nil, nil
}
return ym, nil
}
func (ym *DmIntervalYM) parseIntervYMString(str string) error {
str = strings.ToUpper(str)
ret := strings.Split(str, " ")
l := len(ret)
if l < 3 || !util.StringUtil.EqualsIgnoreCase(ret[0], "INTERVAL") || !(strings.HasPrefix(ret[2], "YEAR") || strings.HasPrefix(ret[2], "MONTH")) {
return ECGO_INVALID_TIME_INTERVAL.throw()
}
ym._type = QUA_YM
yearId := strings.Index(str, "YEAR")
monthId := strings.Index(str, "MONTH")
toId := strings.Index(str, "TO")
var err error
if toId == -1 {
if yearId != -1 && monthId == -1 {
ym._type = QUA_Y
ym.leadScale, err = ym.getLeadPrec(str, yearId)
if err != nil {
return err
}
} else if monthId != -1 && yearId == -1 {
ym._type = QUA_MO
ym.leadScale, err = ym.getLeadPrec(str, monthId)
if err != nil {
return err
}
} else {
return ECGO_INVALID_TIME_INTERVAL.throw()
}
} else {
if yearId == -1 || monthId == -1 {
return ECGO_INVALID_TIME_INTERVAL.throw()
}
ym._type = QUA_YM
ym.leadScale, err = ym.getLeadPrec(str, yearId)
if err != nil {
return err
}
}
ym.scaleForSvr = (int(ym._type) << 8) + (ym.leadScale << 4)
timeVals, err := ym.getTimeValue(ret[1], int(ym._type))
if err != nil {
return err
}
ym.years = timeVals[0]
ym.months = timeVals[1]
return ym.checkScale(ym.leadScale)
}
func (ym *DmIntervalYM) getLeadPrec(str string, startIndex int) (int, error) {
if ym.isLeadScaleSet {
return ym.leadScale, nil
}
leftBtId := strings.Index(str[startIndex:], "(")
rightBtId := strings.Index(str[startIndex:], ")")
leadPrec := 0
if rightBtId == -1 && leftBtId == -1 {
leftBtId += startIndex
rightBtId += startIndex
l := strings.Index(str, "'")
var r int
var dataStr string
if l != -1 {
r = strings.Index(str[l+1:], "'")
if r != -1 {
r += l + 1
}
} else {
r = -1
}
if r != -1 {
dataStr = strings.TrimSpace(str[l+1 : r])
} else {
dataStr = ""
}
if dataStr != "" {
sign := dataStr[0]
if sign == '+' || sign == '-' {
dataStr = strings.TrimSpace(dataStr[1:])
}
end := strings.Index(dataStr, "-")
if end != -1 {
dataStr = dataStr[:end]
}
leadPrec = len(dataStr)
} else {
leadPrec = 2
}
} else if rightBtId != -1 && leftBtId != -1 && rightBtId > leftBtId+1 {
leftBtId += startIndex
rightBtId += startIndex
strPrec := strings.TrimSpace(str[leftBtId+1 : rightBtId])
temp, err := strconv.ParseInt(strPrec, 10, 32)
if err != nil {
return 0, err
}
leadPrec = int(temp)
} else {
return 0, ECGO_INVALID_TIME_INTERVAL.throw()
}
return leadPrec, nil
}
func (ym *DmIntervalYM) checkScale(prec int) error {
switch ym._type {
case QUA_Y:
if prec < len(strconv.FormatInt(int64(math.Abs(float64(ym.years))), 10)) {
return ECGO_INVALID_TIME_INTERVAL.throw()
}
case QUA_YM:
if prec < len(strconv.FormatInt(int64(math.Abs(float64(ym.years))), 10)) {
return ECGO_INVALID_TIME_INTERVAL.throw()
}
if int64(math.Abs(float64(ym.months))) > 11 {
return ECGO_INVALID_TIME_INTERVAL.throw()
}
case QUA_MO:
if prec < len(strconv.FormatInt(int64(math.Abs(float64(ym.months))), 10)) {
return ECGO_INVALID_TIME_INTERVAL.throw()
}
}
return nil
}
func (ym *DmIntervalYM) getTimeValue(subStr string, _type int) ([]int, error) {
hasQuate := false
if subStr[0] == '\'' && subStr[len(subStr)-1] == '\'' {
hasQuate = true
subStr = strings.TrimSpace(subStr[1 : len(subStr)-1])
}
negative := false
if strings.Index(subStr, "-") == 0 {
negative = true
subStr = subStr[1:]
} else if strings.Index(subStr, "+") == 0 {
negative = false
subStr = subStr[1:]
}
if subStr[0] == '\'' && subStr[len(subStr)-1] == '\'' {
hasQuate = true
subStr = strings.TrimSpace(subStr[1 : len(subStr)-1])
}
if !hasQuate {
return nil, ECGO_INVALID_TIME_INTERVAL.throw()
}
lastSignIndex := strings.LastIndex(subStr, "-")
list := make([]string, 2)
if lastSignIndex == -1 || lastSignIndex == 0 {
list[0] = subStr
list[1] = ""
} else {
list[0] = subStr[0:lastSignIndex]
list[1] = subStr[lastSignIndex+1:]
}
var yearVal, monthVal int64
var err error
if ym._type == QUA_YM {
yearVal, err = strconv.ParseInt(list[0], 10, 32)
if err != nil {
return nil, err
}
if util.StringUtil.EqualsIgnoreCase(list[1], "") {
monthVal = 0
} else {
monthVal, err = strconv.ParseInt(list[1], 10, 32)
if err != nil {
return nil, err
}
}
if negative {
yearVal *= -1
monthVal *= -1
}
if yearVal > int64(math.Pow10(ym.leadScale))-1 || yearVal < 1-int64(math.Pow10(ym.leadScale)) {
return nil, ECGO_INVALID_TIME_INTERVAL.throw()
}
} else if ym._type == QUA_Y {
yearVal, err = strconv.ParseInt(list[0], 10, 32)
if err != nil {
return nil, err
}
monthVal = 0
if negative {
yearVal *= -1
}
if yearVal > int64(math.Pow10(ym.leadScale))-1 || yearVal < 1-int64(math.Pow10(ym.leadScale)) {
return nil, ECGO_INVALID_TIME_INTERVAL.throw()
}
} else {
yearVal = 0
monthVal, err = strconv.ParseInt(list[0], 10, 32)
if err != nil {
return nil, err
}
if negative {
monthVal *= -1
}
if monthVal > int64(math.Pow10(ym.leadScale))-1 || monthVal < 1-int64(math.Pow10(ym.leadScale)) {
return nil, ECGO_INVALID_TIME_INTERVAL.throw()
}
}
ret := make([]int, 2)
ret[0] = int(yearVal)
ret[1] = int(monthVal)
return ret, nil
}
func (ym *DmIntervalYM) encode(scale int) ([]byte, error) {
if scale == 0 {
scale = ym.scaleForSvr
}
year, month := ym.years, ym.months
if err := ym.checkScale(ym.leadScale); err != nil {
return nil, err
}
if scale != ym.scaleForSvr {
convertYM, err := ym.convertTo(scale)
if err != nil {
return nil, err
}
year = convertYM.years
month = convertYM.months
} else {
if err := ym.checkScale(ym.leadScale); err != nil {
return nil, err
}
}
bytes := make([]byte, 12)
Dm_build_1346.Dm_build_1362(bytes, 0, int32(year))
Dm_build_1346.Dm_build_1362(bytes, 4, int32(month))
Dm_build_1346.Dm_build_1362(bytes, 8, int32(scale))
return bytes, nil
}
func (ym *DmIntervalYM) convertTo(scale int) (*DmIntervalYM, error) {
destType := (scale & 0x0000FF00) >> 8
leadPrec := (scale >> 4) & 0x0000000F
totalMonths := ym.years*12 + ym.months
year := 0
month := 0
switch destType {
case QUA_Y:
year = totalMonths / 12
if totalMonths%12 >= 6 {
year++
} else if totalMonths%12 <= -6 {
year--
}
if leadPrec < len(strconv.Itoa(int(math.Abs(float64(year))))) {
return nil, ECGO_INVALID_TIME_INTERVAL.throw()
}
case QUA_YM:
year = totalMonths / 12
month = totalMonths % 12
if leadPrec < len(strconv.Itoa(int(math.Abs(float64(year))))) {
return nil, ECGO_INVALID_TIME_INTERVAL.throw()
}
case QUA_MO:
month = totalMonths
if leadPrec < len(strconv.Itoa(int(math.Abs(float64(month))))) {
return nil, ECGO_INVALID_TIME_INTERVAL.throw()
}
}
return &DmIntervalYM{
_type: byte(destType),
years: year,
months: month,
scaleForSvr: scale,
leadScale: (scale >> 4) & 0x0000000F,
Valid: true,
}, nil
}
func (ym *DmIntervalYM) checkValid() error {
if !ym.Valid {
return ECGO_IS_NULL.throw()
}
return nil
}
func (d *DmIntervalYM) GormDataType() string {
return "INTERVAL YEAR TO MONTH"
}
+58
View File
@@ -0,0 +1,58 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import "strings"
type DmResult struct {
filterable
dmStmt *DmStatement
affectedRows int64
insertId int64
}
func newDmResult(bs *DmStatement, execInfo *execRetInfo) *DmResult {
result := DmResult{}
result.resetFilterable(&bs.filterable)
result.dmStmt = bs
result.affectedRows = execInfo.updateCount
if execInfo.lastInsertId == 0 && execInfo.hasResultSet && strings.Index(execInfo.nativeSQL, "/*DMGORM-UPSERT*/") == 0 {
if len(execInfo.rsDatas) > 0 && len(execInfo.rsDatas[0]) > 0 {
result.insertId = Dm_build_1346.Dm_build_1576(execInfo.rsDatas[0][1])
} else {
result.insertId = 0
}
} else {
result.insertId = execInfo.lastInsertId
}
result.idGenerator = dmResultIDGenerator
return &result
}
func (r *DmResult) LastInsertId() (int64, error) {
if len(r.filterChain.filters) == 0 {
return r.lastInsertId()
}
return r.filterChain.reset().DmResultLastInsertId(r)
}
func (r *DmResult) RowsAffected() (int64, error) {
if len(r.filterChain.filters) == 0 {
return r.rowsAffected()
}
return r.filterChain.reset().DmResultRowsAffected(r)
}
func (result *DmResult) lastInsertId() (int64, error) {
return result.insertId, nil
}
func (result *DmResult) rowsAffected() (int64, error) {
return result.affectedRows, nil
}
+30
View File
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
// This is a mirror of golang.org/x/crypto/internal/subtle.
package security
import "unsafe"
// AnyOverlap reports whether x and y share memory at any (not necessarily
// corresponding) index. The memory beyond the slice length is ignored.
func AnyOverlap(x, y []byte) bool {
return len(x) > 0 && len(y) > 0 &&
uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) &&
uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1]))
}
// InexactOverlap reports whether x and y share memory at any non-corresponding
// index. The memory beyond the slice length is ignored. Note that x and y can
// have different lengths and still not have any inexact overlap.
//
// InexactOverlap can be used to implement the requirements of the crypto/cipher
// AEAD, Block, BlockMode and Stream interfaces.
func InexactOverlap(x, y []byte) bool {
if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] {
return false
}
return AnyOverlap(x, y)
}
+11
View File
@@ -0,0 +1,11 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package security
type Cipher interface {
Encrypt(plaintext []byte, genDigest bool) []byte
Decrypt(ciphertext []byte, checkDigest bool) ([]byte, error)
}
+87
View File
@@ -0,0 +1,87 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package security
import (
"crypto/rand"
"errors"
"io"
"math/big"
)
type dhGroup struct {
p *big.Int
g *big.Int
}
func newDhGroup(prime, generator *big.Int) *dhGroup {
return &dhGroup{
p: prime,
g: generator,
}
}
func (dg *dhGroup) P() *big.Int {
p := new(big.Int)
p.Set(dg.p)
return p
}
func (dg *dhGroup) G() *big.Int {
g := new(big.Int)
g.Set(dg.g)
return g
}
// 生成本地公私钥
func (dg *dhGroup) GeneratePrivateKey(randReader io.Reader) (key *DhKey, err error) {
if randReader == nil {
randReader = rand.Reader
}
// 0 < x < p
x, err := rand.Int(randReader, dg.p)
if err != nil {
return
}
zero := big.NewInt(0)
for x.Cmp(zero) == 0 {
x, err = rand.Int(randReader, dg.p)
if err != nil {
return
}
}
key = new(DhKey)
key.x = x
// y = g ^ x mod p
key.y = new(big.Int).Exp(dg.g, x, dg.p)
key.group = dg
return
}
func (dg *dhGroup) ComputeKey(pubkey *DhKey, privkey *DhKey) (kye *DhKey, err error) {
if dg.p == nil {
err = errors.New("DH: invalid group")
return
}
if pubkey.y == nil {
err = errors.New("DH: invalid public key")
return
}
if pubkey.y.Sign() <= 0 || pubkey.y.Cmp(dg.p) >= 0 {
err = errors.New("DH parameter out of bounds")
return
}
if privkey.x == nil {
err = errors.New("DH: invalid private key")
return
}
k := new(big.Int).Exp(pubkey.y, privkey.x, dg.p)
key := new(DhKey)
key.y = k
key.group = dg
return
}
+64
View File
@@ -0,0 +1,64 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package security
import "math/big"
type DhKey struct {
x *big.Int
y *big.Int
group *dhGroup
}
func newPublicKey(s []byte) *DhKey {
key := new(DhKey)
key.y = new(big.Int).SetBytes(s)
return key
}
func (dk *DhKey) GetX() *big.Int {
x := new(big.Int)
x.Set(dk.x)
return x
}
func (dk *DhKey) GetY() *big.Int {
y := new(big.Int)
y.Set(dk.y)
return y
}
func (dk *DhKey) GetYBytes() []byte {
if dk.y == nil {
return nil
}
if dk.group != nil {
blen := (dk.group.p.BitLen() + 7) / 8
ret := make([]byte, blen)
copyWithLeftPad(ret, dk.y.Bytes())
return ret
}
return dk.y.Bytes()
}
func (dk *DhKey) GetYString() string {
if dk.y == nil {
return ""
}
return dk.y.String()
}
func (dk *DhKey) IsPrivateKey() bool {
return dk.x != nil
}
func copyWithLeftPad(dest, src []byte) {
numPaddingBytes := len(dest) - len(src)
for i := 0; i < numPaddingBytes; i++ {
dest[i] = 0
}
copy(dest[:numPaddingBytes], src)
}
+69
View File
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
// go官方没有实现ecb加密模式
package security
import (
"crypto/cipher"
)
type ecb struct {
b cipher.Block
blockSize int
}
func newECB(b cipher.Block) *ecb {
return &ecb{
b: b,
blockSize: b.BlockSize(),
}
}
type ecbEncrypter ecb
func NewECBEncrypter(b cipher.Block) cipher.BlockMode {
return (*ecbEncrypter)(newECB(b))
}
func (x *ecbEncrypter) BlockSize() int { return x.blockSize }
func (x *ecbEncrypter) CryptBlocks(dst, src []byte) {
if len(src)%x.blockSize != 0 {
panic("dm/security: input not full blocks")
}
if len(dst) < len(src) {
panic("dm/security: output smaller than input")
}
if InexactOverlap(dst[:len(src)], src) {
panic("dm/security: invalid buffer overlap")
}
for bs, be := 0, x.blockSize; bs < len(src); bs, be = bs+x.blockSize, be+x.blockSize {
x.b.Encrypt(dst[bs:be], src[bs:be])
}
}
type ecbDecrypter ecb
func NewECBDecrypter(b cipher.Block) cipher.BlockMode {
return (*ecbDecrypter)(newECB(b))
}
func (x *ecbDecrypter) BlockSize() int { return x.blockSize }
func (x *ecbDecrypter) CryptBlocks(dst, src []byte) {
if len(src)%x.blockSize != 0 {
panic("dm/security: input not full blocks")
}
if len(dst) < len(src) {
panic("dm/security: output smaller than input")
}
if InexactOverlap(dst[:len(src)], src) {
panic("dm/security: invalid buffer overlap")
}
for bs, be := 0, x.blockSize; bs < len(src); bs, be = bs+x.blockSize, be+x.blockSize {
x.b.Decrypt(dst[bs:be], src[bs:be])
}
}
+114
View File
@@ -0,0 +1,114 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package security
import (
"math/big"
)
const (
DH_KEY_LENGTH int = 64
/* 低7位用于保存分组加密算法中的工作模式 */
WORK_MODE_MASK int = 0x007f
ECB_MODE int = 0x1
CBC_MODE int = 0x2
CFB_MODE int = 0x4
OFB_MODE int = 0x8
/* 高位保存加密算法 */
ALGO_MASK int = 0xff80
DES int = 0x0080
DES3 int = 0x0100
AES128 int = 0x0200
AES192 int = 0x0400
AES256 int = 0x0800
RC4 int = 0x1000
MD5 int = 0x1100
// 用户名密码加密算法
DES_CFB int = 132
// 消息加密摘要长度
MD5_DIGEST_SIZE int = 16
MIN_EXTERNAL_CIPHER_ID int = 5000
)
var dhParaP = "C009D877BAF5FAF416B7F778E6115DCB90D65217DCC2F08A9DFCB5A192C593EBAB02929266B8DBFC2021039FDBD4B7FDE2B996E00008F57AE6EFB4ED3F17B6D3"
var dhParaG = "5"
var defaultIV = []byte{0x20, 0x21, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a,
0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x20}
var p *big.Int
var g *big.Int
func NewClientKeyPair() (key *DhKey, err error) {
p, _ = new(big.Int).SetString(dhParaP, 16)
g, _ = new(big.Int).SetString(dhParaG, 16)
dhGroup := newDhGroup(p, g)
key, err = dhGroup.GeneratePrivateKey(nil)
if err != nil {
return nil, err
}
return key, nil
}
func ComputeSessionKey(clientPrivKey *DhKey, serverPubKey []byte) []byte {
serverKeyX := bytes2Bn(serverPubKey)
clientPrivKeyX := clientPrivKey.GetX()
sessionKeyBN := serverKeyX.Exp(serverKeyX, clientPrivKeyX, p)
return Bn2Bytes(sessionKeyBN, 0)
}
func bytes2Bn(bnBytesSrc []byte) *big.Int {
if bnBytesSrc == nil {
return nil
}
if bnBytesSrc[0] == 0 {
return new(big.Int).SetBytes(bnBytesSrc)
}
validBytesCount := len(bnBytesSrc) + 1
bnBytesTo := make([]byte, validBytesCount)
bnBytesTo[0] = 0
copy(bnBytesTo[1:validBytesCount], bnBytesSrc)
return new(big.Int).SetBytes(bnBytesTo)
}
func Bn2Bytes(bn *big.Int, bnLen int) []byte {
var bnBytesSrc, bnBytesTemp, bnBytesTo []byte
var leading_zero_count int
validBytesCount := 0
if bn == nil {
return nil
}
bnBytesSrc = bn.Bytes()
// 去除首位0
if bnBytesSrc[0] != 0 {
bnBytesTemp = bnBytesSrc
validBytesCount = len(bnBytesTemp)
} else {
validBytesCount = len(bnBytesSrc) - 1
bnBytesTemp = make([]byte, validBytesCount)
copy(bnBytesTemp, bnBytesSrc[1:validBytesCount+1])
}
if bnLen == 0 {
leading_zero_count = 0
} else {
leading_zero_count = bnLen - validBytesCount
}
// 如果位数不足DH_KEY_LENGTH则在前面补0
if leading_zero_count > 0 {
bnBytesTo = make([]byte, DH_KEY_LENGTH)
i := 0
for i = 0; i < leading_zero_count; i++ {
bnBytesTo[i] = 0
}
copy(bnBytesTo[i:i+validBytesCount], bnBytesTemp)
} else {
bnBytesTo = bnBytesTemp
}
return bnBytesTo
}
+211
View File
@@ -0,0 +1,211 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package security
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/des"
"crypto/md5"
"crypto/rc4"
"errors"
"reflect"
)
type SymmCipher struct {
encryptCipher interface{} //cipher.BlockMode | cipher.Stream
decryptCipher interface{} //cipher.BlockMode | cipher.Stream
key []byte
block cipher.Block // 分组加密算法
algorithmType int
workMode int
needPadding bool
}
func NewSymmCipher(algorithmID int, key []byte) (SymmCipher, error) {
var sc SymmCipher
var err error
sc.key = key
sc.algorithmType = algorithmID & ALGO_MASK
sc.workMode = algorithmID & WORK_MODE_MASK
switch sc.algorithmType {
case AES128:
if sc.block, err = aes.NewCipher(key[:16]); err != nil {
return sc, err
}
case AES192:
if sc.block, err = aes.NewCipher(key[:24]); err != nil {
return sc, err
}
case AES256:
if sc.block, err = aes.NewCipher(key[:32]); err != nil {
return sc, err
}
case DES:
if sc.block, err = des.NewCipher(key[:8]); err != nil {
return sc, err
}
case DES3:
var tripleDESKey []byte
tripleDESKey = append(tripleDESKey, key[:16]...)
tripleDESKey = append(tripleDESKey, key[:8]...)
if sc.block, err = des.NewTripleDESCipher(tripleDESKey); err != nil {
return sc, err
}
case RC4:
if sc.encryptCipher, err = rc4.NewCipher(key[:16]); err != nil {
return sc, err
}
if sc.decryptCipher, err = rc4.NewCipher(key[:16]); err != nil {
return sc, err
}
return sc, nil
default:
return sc, errors.New("invalidCipher")
}
blockSize := sc.block.BlockSize()
if sc.encryptCipher, err = sc.getEncrypter(sc.workMode, sc.block, defaultIV[:blockSize]); err != nil {
return sc, err
}
if sc.decryptCipher, err = sc.getDecrypter(sc.workMode, sc.block, defaultIV[:blockSize]); err != nil {
return sc, err
}
return sc, nil
}
func (sc SymmCipher) Encrypt(plaintext []byte, genDigest bool) []byte {
// 执行过加密后,IV值变了,需要重新初始化encryptCipher对象(因为没有类似resetIV的方法)
if sc.algorithmType != RC4 {
sc.encryptCipher, _ = sc.getEncrypter(sc.workMode, sc.block, defaultIV[:sc.block.BlockSize()])
} else {
sc.encryptCipher, _ = rc4.NewCipher(sc.key[:16])
}
// 填充
var paddingtext = make([]byte, len(plaintext))
copy(paddingtext, plaintext)
if sc.needPadding {
paddingtext = pkcs5Padding(paddingtext)
}
ret := make([]byte, len(paddingtext))
if v, ok := sc.encryptCipher.(cipher.Stream); ok {
v.XORKeyStream(ret, paddingtext)
} else if v, ok := sc.encryptCipher.(cipher.BlockMode); ok {
v.CryptBlocks(ret, paddingtext)
}
// md5摘要
if genDigest {
digest := md5.Sum(plaintext)
encrypt := ret
ret = make([]byte, len(encrypt)+len(digest))
copy(ret[:len(encrypt)], encrypt)
copy(ret[len(encrypt):], digest[:])
}
return ret
}
func (sc SymmCipher) Decrypt(ciphertext []byte, checkDigest bool) ([]byte, error) {
// 执行过解密后,IV值变了,需要重新初始化decryptCipher对象(因为没有类似resetIV的方法)
if sc.algorithmType != RC4 {
sc.decryptCipher, _ = sc.getDecrypter(sc.workMode, sc.block, defaultIV[:sc.block.BlockSize()])
} else {
sc.decryptCipher, _ = rc4.NewCipher(sc.key[:16])
}
var ret []byte
if checkDigest {
var digest = ciphertext[len(ciphertext)-MD5_DIGEST_SIZE:]
ret = ciphertext[:len(ciphertext)-MD5_DIGEST_SIZE]
ret = sc.decrypt(ret)
var msgDigest = md5.Sum(ret)
if !reflect.DeepEqual(msgDigest[:], digest) {
return nil, errors.New("Decrypt failed/Digest not match\n")
}
} else {
ret = sc.decrypt(ciphertext)
}
return ret, nil
}
func (sc SymmCipher) decrypt(ciphertext []byte) []byte {
ret := make([]byte, len(ciphertext))
if v, ok := sc.decryptCipher.(cipher.Stream); ok {
v.XORKeyStream(ret, ciphertext)
} else if v, ok := sc.decryptCipher.(cipher.BlockMode); ok {
v.CryptBlocks(ret, ciphertext)
}
// 去除填充
if sc.needPadding {
ret = pkcs5UnPadding(ret)
}
return ret
}
func (sc *SymmCipher) getEncrypter(workMode int, block cipher.Block, iv []byte) (ret interface{}, err error) {
switch workMode {
case ECB_MODE:
ret = NewECBEncrypter(block)
sc.needPadding = true
case CBC_MODE:
ret = cipher.NewCBCEncrypter(block, iv)
sc.needPadding = true
case CFB_MODE:
ret = cipher.NewCFBEncrypter(block, iv)
sc.needPadding = false
case OFB_MODE:
ret = cipher.NewOFB(block, iv)
sc.needPadding = false
default:
err = errors.New("invalidCipherMode")
}
return
}
func (sc *SymmCipher) getDecrypter(workMode int, block cipher.Block, iv []byte) (ret interface{}, err error) {
switch workMode {
case ECB_MODE:
ret = NewECBDecrypter(block)
sc.needPadding = true
case CBC_MODE:
ret = cipher.NewCBCDecrypter(block, iv)
sc.needPadding = true
case CFB_MODE:
ret = cipher.NewCFBDecrypter(block, iv)
sc.needPadding = false
case OFB_MODE:
ret = cipher.NewOFB(block, iv)
sc.needPadding = false
default:
err = errors.New("invalidCipherMode")
}
return
}
// 补码
func pkcs77Padding(ciphertext []byte, blocksize int) []byte {
padding := blocksize - len(ciphertext)%blocksize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
// 去码
func pkcs7UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:length-unpadding]
}
// 补码
func pkcs5Padding(ciphertext []byte) []byte {
return pkcs77Padding(ciphertext, 8)
}
// 去码
func pkcs5UnPadding(ciphertext []byte) []byte {
return pkcs7UnPadding(ciphertext)
}
+142
View File
@@ -0,0 +1,142 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package security
import (
"crypto/md5"
"errors"
"fmt"
"reflect"
"unsafe"
)
type ThirdPartCipher struct {
encryptType int // 外部加密算法id
encryptName string // 外部加密算法名称
hashType int
key []byte
cipherCount int // 外部加密算法个数
//innerId int // 外部加密算法内部id
blockSize int // 分组块大小
khSize int // key/hash大小
}
func NewThirdPartCipher(encryptType int, key []byte, cipherPath string, hashType int) (ThirdPartCipher, error) {
var tpc = ThirdPartCipher{
encryptType: encryptType,
key: key,
hashType: hashType,
cipherCount: -1,
}
var err error
err = initThirdPartCipher(cipherPath)
if err != nil {
return tpc, err
}
tpc.getCount()
if err = tpc.getInfo(); err != nil {
return tpc, err
}
return tpc, nil
}
func (tpc *ThirdPartCipher) getCount() int {
if tpc.cipherCount == -1 {
tpc.cipherCount = cipherGetCount()
}
return tpc.cipherCount
}
func (tpc *ThirdPartCipher) getInfo() error {
var cipher_id, ty, blk_size, kh_size int
//var strptr, _ = syscall.UTF16PtrFromString(tpc.encryptName)
var strptr *uint16 = new(uint16)
for i := 1; i <= tpc.getCount(); i++ {
cipherGetInfo(uintptr(i), uintptr(unsafe.Pointer(&cipher_id)), uintptr(unsafe.Pointer(&strptr)),
uintptr(unsafe.Pointer(&ty)), uintptr(unsafe.Pointer(&blk_size)), uintptr(unsafe.Pointer(&kh_size)))
if tpc.encryptType == cipher_id {
tpc.blockSize = blk_size
tpc.khSize = kh_size
tpc.encryptName = string(uintptr2bytes(uintptr(unsafe.Pointer(strptr))))
return nil
}
}
return fmt.Errorf("ThirdPartyCipher: cipher id:%d not found", tpc.encryptType)
}
func (tpc ThirdPartCipher) Encrypt(plaintext []byte, genDigest bool) []byte {
var tmp_para uintptr
cipherEncryptInit(uintptr(tpc.encryptType), uintptr(unsafe.Pointer(&tpc.key[0])), uintptr(len(tpc.key)), tmp_para)
ciphertextLen := cipherGetCipherTextSize(uintptr(tpc.encryptType), tmp_para, uintptr(len(plaintext)))
ciphertext := make([]byte, ciphertextLen)
ret := cipherEncrypt(uintptr(tpc.encryptType), tmp_para, uintptr(unsafe.Pointer(&plaintext[0])), uintptr(len(plaintext)),
uintptr(unsafe.Pointer(&ciphertext[0])), uintptr(len(ciphertext)))
ciphertext = ciphertext[:ret]
cipherClean(uintptr(tpc.encryptType), tmp_para)
// md5摘要
if genDigest {
digest := md5.Sum(plaintext)
encrypt := ciphertext
ciphertext = make([]byte, len(encrypt)+len(digest))
copy(ciphertext[:len(encrypt)], encrypt)
copy(ciphertext[len(encrypt):], digest[:])
}
return ciphertext
}
func (tpc ThirdPartCipher) Decrypt(ciphertext []byte, checkDigest bool) ([]byte, error) {
var ret []byte
if checkDigest {
var digest = ciphertext[len(ciphertext)-MD5_DIGEST_SIZE:]
ret = ciphertext[:len(ciphertext)-MD5_DIGEST_SIZE]
ret = tpc.decrypt(ret)
var msgDigest = md5.Sum(ret)
if !reflect.DeepEqual(msgDigest[:], digest) {
return nil, errors.New("Decrypt failed/Digest not match\n")
}
} else {
ret = tpc.decrypt(ciphertext)
}
return ret, nil
}
func (tpc ThirdPartCipher) decrypt(ciphertext []byte) []byte {
var tmp_para uintptr
cipherDecryptInit(uintptr(tpc.encryptType), uintptr(unsafe.Pointer(&tpc.key[0])), uintptr(len(tpc.key)), tmp_para)
plaintext := make([]byte, len(ciphertext))
ret := cipherDecrypt(uintptr(tpc.encryptType), tmp_para, uintptr(unsafe.Pointer(&ciphertext[0])), uintptr(len(ciphertext)),
uintptr(unsafe.Pointer(&plaintext[0])), uintptr(len(plaintext)))
plaintext = plaintext[:ret]
cipherClean(uintptr(tpc.encryptType), tmp_para)
return plaintext
}
func addBufSize(buf []byte, newCap int) []byte {
newBuf := make([]byte, newCap)
copy(newBuf, buf)
return newBuf
}
func uintptr2bytes(p uintptr) []byte {
buf := make([]byte, 64)
i := 0
for b := (*byte)(unsafe.Pointer(p)); *b != 0; i++ {
if i > cap(buf) {
buf = addBufSize(buf, i*2)
}
buf[i] = *b
// byte占1字节
p++
b = (*byte)(unsafe.Pointer(p))
}
return buf[:i]
}
+96
View File
@@ -0,0 +1,96 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package security
import "plugin"
var (
dmCipherEncryptSo *plugin.Plugin
cipherGetCountProc plugin.Symbol
cipherGetInfoProc plugin.Symbol
cipherEncryptInitProc plugin.Symbol
cipherGetCipherTextSizeProc plugin.Symbol
cipherEncryptProc plugin.Symbol
cipherCleanupProc plugin.Symbol
cipherDecryptInitProc plugin.Symbol
cipherDecryptProc plugin.Symbol
)
func initThirdPartCipher(cipherPath string) (err error) {
if dmCipherEncryptSo, err = plugin.Open(cipherPath); err != nil {
return err
}
if cipherGetCountProc, err = dmCipherEncryptSo.Lookup("cipher_get_count"); err != nil {
return err
}
if cipherGetInfoProc, err = dmCipherEncryptSo.Lookup("cipher_get_info"); err != nil {
return err
}
if cipherEncryptInitProc, err = dmCipherEncryptSo.Lookup("cipher_encrypt_init"); err != nil {
return err
}
if cipherGetCipherTextSizeProc, err = dmCipherEncryptSo.Lookup("cipher_get_cipher_text_size"); err != nil {
return err
}
if cipherEncryptProc, err = dmCipherEncryptSo.Lookup("cipher_encrypt"); err != nil {
return err
}
if cipherCleanupProc, err = dmCipherEncryptSo.Lookup("cipher_cleanup"); err != nil {
return err
}
if cipherDecryptInitProc, err = dmCipherEncryptSo.Lookup("cipher_decrypt_init"); err != nil {
return err
}
if cipherDecryptProc, err = dmCipherEncryptSo.Lookup("cipher_decrypt"); err != nil {
return err
}
return nil
}
func cipherGetCount() int {
ret := cipherGetCountProc.(func() interface{})()
return ret.(int)
}
func cipherGetInfo(seqno, cipherId, cipherName, _type, blkSize, khSIze uintptr) {
ret := cipherGetInfoProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(seqno, cipherId, cipherName, _type, blkSize, khSIze)
if ret.(int) == 0 {
panic("ThirdPartyCipher: call cipher_get_info failed")
}
}
func cipherEncryptInit(cipherId, key, keySize, cipherPara uintptr) {
ret := cipherEncryptInitProc.(func(uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, key, keySize, cipherPara)
if ret.(int) == 0 {
panic("ThirdPartyCipher: call cipher_encrypt_init failed")
}
}
func cipherGetCipherTextSize(cipherId, cipherPara, plainTextSize uintptr) uintptr {
ciphertextLen := cipherGetCipherTextSizeProc.(func(uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, plainTextSize)
return ciphertextLen.(uintptr)
}
func cipherEncrypt(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize uintptr) uintptr {
ret := cipherEncryptProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize)
return ret.(uintptr)
}
func cipherClean(cipherId, cipherPara uintptr) {
cipherEncryptProc.(func(uintptr, uintptr))(cipherId, cipherPara)
}
func cipherDecryptInit(cipherId, key, keySize, cipherPara uintptr) {
ret := cipherDecryptInitProc.(func(uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, key, keySize, cipherPara)
if ret.(int) == 0 {
panic("ThirdPartyCipher: call cipher_decrypt_init failed")
}
}
func cipherDecrypt(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize uintptr) uintptr {
ret := cipherDecryptProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize)
return ret.(uintptr)
}
+96
View File
@@ -0,0 +1,96 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package security
import "plugin"
var (
dmCipherEncryptSo *plugin.Plugin
cipherGetCountProc plugin.Symbol
cipherGetInfoProc plugin.Symbol
cipherEncryptInitProc plugin.Symbol
cipherGetCipherTextSizeProc plugin.Symbol
cipherEncryptProc plugin.Symbol
cipherCleanupProc plugin.Symbol
cipherDecryptInitProc plugin.Symbol
cipherDecryptProc plugin.Symbol
)
func initThirdPartCipher(cipherPath string) (err error) {
if dmCipherEncryptSo, err = plugin.Open(cipherPath); err != nil {
return err
}
if cipherGetCountProc, err = dmCipherEncryptSo.Lookup("cipher_get_count"); err != nil {
return err
}
if cipherGetInfoProc, err = dmCipherEncryptSo.Lookup("cipher_get_info"); err != nil {
return err
}
if cipherEncryptInitProc, err = dmCipherEncryptSo.Lookup("cipher_encrypt_init"); err != nil {
return err
}
if cipherGetCipherTextSizeProc, err = dmCipherEncryptSo.Lookup("cipher_get_cipher_text_size"); err != nil {
return err
}
if cipherEncryptProc, err = dmCipherEncryptSo.Lookup("cipher_encrypt"); err != nil {
return err
}
if cipherCleanupProc, err = dmCipherEncryptSo.Lookup("cipher_cleanup"); err != nil {
return err
}
if cipherDecryptInitProc, err = dmCipherEncryptSo.Lookup("cipher_decrypt_init"); err != nil {
return err
}
if cipherDecryptProc, err = dmCipherEncryptSo.Lookup("cipher_decrypt"); err != nil {
return err
}
return nil
}
func cipherGetCount() int {
ret := cipherGetCountProc.(func() interface{})()
return ret.(int)
}
func cipherGetInfo(seqno, cipherId, cipherName, _type, blkSize, khSIze uintptr) {
ret := cipherGetInfoProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(seqno, cipherId, cipherName, _type, blkSize, khSIze)
if ret.(int) == 0 {
panic("ThirdPartyCipher: call cipher_get_info failed")
}
}
func cipherEncryptInit(cipherId, key, keySize, cipherPara uintptr) {
ret := cipherEncryptInitProc.(func(uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, key, keySize, cipherPara)
if ret.(int) == 0 {
panic("ThirdPartyCipher: call cipher_encrypt_init failed")
}
}
func cipherGetCipherTextSize(cipherId, cipherPara, plainTextSize uintptr) uintptr {
ciphertextLen := cipherGetCipherTextSizeProc.(func(uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, plainTextSize)
return ciphertextLen.(uintptr)
}
func cipherEncrypt(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize uintptr) uintptr {
ret := cipherEncryptProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize)
return ret.(uintptr)
}
func cipherClean(cipherId, cipherPara uintptr) {
cipherEncryptProc.(func(uintptr, uintptr))(cipherId, cipherPara)
}
func cipherDecryptInit(cipherId, key, keySize, cipherPara uintptr) {
ret := cipherDecryptInitProc.(func(uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, key, keySize, cipherPara)
if ret.(int) == 0 {
panic("ThirdPartyCipher: call cipher_decrypt_init failed")
}
}
func cipherDecrypt(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize uintptr) uintptr {
ret := cipherDecryptProc.(func(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) interface{})(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize)
return ret.(uintptr)
}
+83
View File
@@ -0,0 +1,83 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package security
import (
"syscall"
)
var (
dmCipherEncryptDLL *syscall.LazyDLL
cipherGetCountProc *syscall.LazyProc
cipherGetInfoProc *syscall.LazyProc
cipherEncryptInitProc *syscall.LazyProc
cipherGetCipherTextSizeProc *syscall.LazyProc
cipherEncryptProc *syscall.LazyProc
cipherCleanupProc *syscall.LazyProc
cipherDecryptInitProc *syscall.LazyProc
cipherDecryptProc *syscall.LazyProc
)
func initThirdPartCipher(cipherPath string) error {
dmCipherEncryptDLL = syscall.NewLazyDLL(cipherPath)
if err := dmCipherEncryptDLL.Load(); err != nil {
return err
}
cipherGetCountProc = dmCipherEncryptDLL.NewProc("cipher_get_count")
cipherGetInfoProc = dmCipherEncryptDLL.NewProc("cipher_get_info")
cipherEncryptInitProc = dmCipherEncryptDLL.NewProc("cipher_encrypt_init")
cipherGetCipherTextSizeProc = dmCipherEncryptDLL.NewProc("cipher_get_cipher_text_size")
cipherEncryptProc = dmCipherEncryptDLL.NewProc("cipher_encrypt")
cipherCleanupProc = dmCipherEncryptDLL.NewProc("cipher_cleanup")
cipherDecryptInitProc = dmCipherEncryptDLL.NewProc("cipher_decrypt_init")
cipherDecryptProc = dmCipherEncryptDLL.NewProc("cipher_decrypt")
return nil
}
func cipherGetCount() int {
ret, _, _ := cipherGetCountProc.Call()
return int(ret)
}
func cipherGetInfo(seqno, cipherId, cipherName, _type, blkSize, khSIze uintptr) {
ret, _, _ := cipherGetInfoProc.Call(seqno, cipherId, cipherName, _type, blkSize, khSIze)
if ret == 0 {
panic("ThirdPartyCipher: call cipher_get_info failed")
}
}
func cipherEncryptInit(cipherId, key, keySize, cipherPara uintptr) {
ret, _, _ := cipherEncryptInitProc.Call(cipherId, key, keySize, cipherPara)
if ret == 0 {
panic("ThirdPartyCipher: call cipher_encrypt_init failed")
}
}
func cipherGetCipherTextSize(cipherId, cipherPara, plainTextSize uintptr) uintptr {
ciphertextLen, _, _ := cipherGetCipherTextSizeProc.Call(cipherId, cipherPara, plainTextSize)
return ciphertextLen
}
func cipherEncrypt(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize uintptr) uintptr {
ret, _, _ := cipherEncryptProc.Call(cipherId, cipherPara, plainText, plainTextSize, cipherText, cipherTextBufSize)
return ret
}
func cipherClean(cipherId, cipherPara uintptr) {
_, _, _ = cipherCleanupProc.Call(cipherId, cipherPara)
}
func cipherDecryptInit(cipherId, key, keySize, cipherPara uintptr) {
ret, _, _ := cipherDecryptInitProc.Call(cipherId, key, keySize, cipherPara)
if ret == 0 {
panic("ThirdPartyCipher: call cipher_decrypt_init failed")
}
}
func cipherDecrypt(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize uintptr) uintptr {
ret, _, _ := cipherDecryptProc.Call(cipherId, cipherPara, cipherText, cipherTextSize, plainText, plainTextBufSize)
return ret
}
+37
View File
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package security
import (
"crypto/tls"
"errors"
"net"
"sync"
)
//var dmHome = flag.String("DM_HOME", "", "Where DMDB installed")
var flagLock = sync.Mutex{}
func NewTLSFromTCP(conn net.Conn, sslCertPath string, sslKeyPath string, user string) (*tls.Conn, error) {
if sslCertPath == "" && sslKeyPath == "" {
// 用户必须手动指定ssl文件和签名(.cert文件)
return nil, errors.New("sslCertPath and sslKeyPath can not be empty!")
}
cer, err := tls.LoadX509KeyPair(sslCertPath, sslKeyPath)
if err != nil {
return nil, err
}
conf := &tls.Config{
InsecureSkipVerify: true,
Certificates: []tls.Certificate{cer},
}
tlsConn := tls.Client(conn, conf)
if err := tlsConn.Handshake(); err != nil {
return nil, err
}
return tlsConn, nil
}
+522
View File
@@ -0,0 +1,522 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"database/sql/driver"
"io"
"reflect"
"strings"
)
type DmRows struct {
filterable
CurrentRows *innerRows
finish func()
}
func (r *DmRows) Columns() []string {
if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
return nil
}
if len(r.filterChain.filters) == 0 {
return r.columns()
}
return r.filterChain.reset().DmRowsColumns(r)
}
func (r *DmRows) Close() error {
if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
return err
}
if len(r.filterChain.filters) == 0 {
return r.close()
}
return r.filterChain.reset().DmRowsClose(r)
}
func (r *DmRows) Next(dest []driver.Value) error {
if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
return err
}
if len(r.filterChain.filters) == 0 {
return r.next(dest)
}
return r.filterChain.reset().DmRowsNext(r, dest)
}
func (r *DmRows) HasNextResultSet() bool {
if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
return false
}
if len(r.filterChain.filters) == 0 {
return r.hasNextResultSet()
}
return r.filterChain.reset().DmRowsHasNextResultSet(r)
}
func (r *DmRows) NextResultSet() error {
if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
return err
}
if len(r.filterChain.filters) == 0 {
return r.nextResultSet()
}
return r.filterChain.reset().DmRowsNextResultSet(r)
}
func (r *DmRows) ColumnTypeScanType(index int) reflect.Type {
if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
return nil
}
if len(r.filterChain.filters) == 0 {
return r.columnTypeScanType(index)
}
return r.filterChain.reset().DmRowsColumnTypeScanType(r, index)
}
func (r *DmRows) ColumnTypeDatabaseTypeName(index int) string {
if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
return ""
}
if len(r.filterChain.filters) == 0 {
return r.columnTypeDatabaseTypeName(index)
}
return r.filterChain.reset().DmRowsColumnTypeDatabaseTypeName(r, index)
}
func (r *DmRows) ColumnTypeLength(index int) (length int64, ok bool) {
if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
return -1, false
}
if len(r.filterChain.filters) == 0 {
return r.columnTypeLength(index)
}
return r.filterChain.reset().DmRowsColumnTypeLength(r, index)
}
func (r *DmRows) ColumnTypeNullable(index int) (nullable, ok bool) {
if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
return false, false
}
if len(r.filterChain.filters) == 0 {
return r.columnTypeNullable(index)
}
return r.filterChain.reset().DmRowsColumnTypeNullable(r, index)
}
func (r *DmRows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) {
if err := r.CurrentRows.dmStmt.checkClosed(); err != nil {
return -1, -1, false
}
if len(r.filterChain.filters) == 0 {
return r.columnTypePrecisionScale(index)
}
return r.filterChain.reset().DmRowsColumnTypePrecisionScale(r, index)
}
func (dest *DmRows) Scan(src interface{}) error {
switch src := src.(type) {
case nil:
*dest = *new(DmRows)
return nil
case *DmRows:
*dest = *src
return nil
default:
return UNSUPPORTED_SCAN
}
}
func (rows *DmRows) columns() []string {
return rows.CurrentRows.Columns()
}
func (rows *DmRows) close() error {
if f := rows.finish; f != nil {
f()
rows.finish = nil
}
return rows.CurrentRows.Close()
}
func (rows *DmRows) next(dest []driver.Value) error {
return rows.CurrentRows.Next(dest)
}
func (rows *DmRows) hasNextResultSet() bool {
return rows.CurrentRows.HasNextResultSet()
}
func (rows *DmRows) nextResultSet() error {
return rows.CurrentRows.NextResultSet()
}
func (rows *DmRows) columnTypeScanType(index int) reflect.Type {
return rows.CurrentRows.ColumnTypeScanType(index)
}
func (rows *DmRows) columnTypeDatabaseTypeName(index int) string {
return rows.CurrentRows.ColumnTypeDatabaseTypeName(index)
}
func (rows *DmRows) columnTypeLength(index int) (length int64, ok bool) {
return rows.CurrentRows.ColumnTypeLength(index)
}
func (rows *DmRows) columnTypeNullable(index int) (nullable, ok bool) {
return rows.CurrentRows.ColumnTypeNullable(index)
}
func (rows *DmRows) columnTypePrecisionScale(index int) (precision, scale int64, ok bool) {
return rows.CurrentRows.ColumnTypePrecisionScale(index)
}
type innerRows struct {
dmStmt *DmStatement
id int16
columns []column
datas [][][]byte
datasOffset int
datasStartPos int64
currentPos int64
totalRowCount int64
fetchSize int
sizeOfRow int
isBdta bool
nextExecInfo *execRetInfo
next *innerRows
dmRows *DmRows
closed bool
}
func (innerRows *innerRows) checkClosed() error {
if innerRows.closed {
return ECGO_RESULTSET_CLOSED.throw()
}
return nil
}
func (innerRows *innerRows) Columns() []string {
if err := innerRows.checkClosed(); err != nil {
return nil
}
columnNames := make([]string, len(innerRows.columns))
nameCase := innerRows.dmStmt.dmConn.dmConnector.columnNameCase
for i, column := range innerRows.columns {
if nameCase == COLUMN_NAME_NATURAL_CASE {
columnNames[i] = column.name
} else if nameCase == COLUMN_NAME_UPPER_CASE {
columnNames[i] = strings.ToUpper(column.name)
} else if nameCase == COLUMN_NAME_LOWER_CASE {
columnNames[i] = strings.ToLower(column.name)
} else {
columnNames[i] = column.name
}
}
return columnNames
}
func (innerRows *innerRows) Close() error {
if innerRows.closed {
return nil
}
innerRows.closed = true
if innerRows.dmStmt.innerUsed {
innerRows.dmStmt.close()
} else {
delete(innerRows.dmStmt.rsMap, innerRows.id)
}
innerRows.dmStmt = nil
return nil
}
func (innerRows *innerRows) Next(dest []driver.Value) error {
err := innerRows.checkClosed()
if err != nil {
return err
}
if innerRows.totalRowCount == 0 || innerRows.currentPos >= innerRows.totalRowCount {
return io.EOF
}
if innerRows.currentPos+1 == innerRows.totalRowCount {
innerRows.currentPos++
innerRows.datasOffset++
return io.EOF
}
if innerRows.currentPos+1 < innerRows.datasStartPos || innerRows.currentPos+1 >= innerRows.datasStartPos+int64(len(innerRows.datas)) {
if innerRows.fetchData(innerRows.currentPos + 1) {
innerRows.currentPos++
err := innerRows.getRowData(dest)
if err != nil {
return err
}
} else {
innerRows.currentPos++
innerRows.datasOffset++
return io.EOF
}
} else {
innerRows.currentPos++
innerRows.datasOffset++
err := innerRows.getRowData(dest)
if err != nil {
return err
}
}
return nil
}
func (innerRows *innerRows) HasNextResultSet() bool {
err := innerRows.checkClosed()
if err != nil {
return false
}
if innerRows.nextExecInfo != nil {
return innerRows.nextExecInfo.hasResultSet
}
innerRows.nextExecInfo, err = innerRows.dmStmt.dmConn.Access.Dm_build_543(innerRows.dmStmt, 0)
if err != nil {
return false
}
if innerRows.nextExecInfo.hasResultSet {
innerRows.next = newInnerRows(innerRows.id+1, innerRows.dmStmt, innerRows.nextExecInfo)
return true
}
return false
}
func (innerRows *innerRows) NextResultSet() error {
err := innerRows.checkClosed()
if err != nil {
return err
}
if innerRows.nextExecInfo == nil {
innerRows.HasNextResultSet()
}
if innerRows.next == nil {
return io.EOF
}
innerRows.next.dmRows = innerRows.dmRows
innerRows.dmRows.CurrentRows = innerRows.next
return nil
}
func (innerRows *innerRows) ColumnTypeScanType(index int) reflect.Type {
if err := innerRows.checkClosed(); err != nil {
return nil
}
if column := innerRows.checkIndex(index); column != nil {
return column.ScanType()
}
return nil
}
func (innerRows *innerRows) ColumnTypeDatabaseTypeName(index int) string {
if err := innerRows.checkClosed(); err != nil {
return ""
}
if column := innerRows.checkIndex(index); column != nil {
return column.typeName
}
return ""
}
func (innerRows *innerRows) ColumnTypeLength(index int) (length int64, ok bool) {
if err := innerRows.checkClosed(); err != nil {
return 0, false
}
if column := innerRows.checkIndex(index); column != nil {
return column.Length()
}
return 0, false
}
func (innerRows *innerRows) ColumnTypeNullable(index int) (nullable, ok bool) {
if err := innerRows.checkClosed(); err != nil {
return false, false
}
if column := innerRows.checkIndex(index); column != nil {
return column.nullable, true
}
return false, false
}
func (innerRows *innerRows) ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) {
if err := innerRows.checkClosed(); err != nil {
return 0, 0, false
}
if column := innerRows.checkIndex(index); column != nil {
return column.PrecisionScale()
}
return 0, 0, false
}
func newDmRows(currentRows *innerRows) *DmRows {
dr := new(DmRows)
dr.resetFilterable(&currentRows.dmStmt.filterable)
dr.CurrentRows = currentRows
dr.idGenerator = dmRowsIDGenerator
currentRows.dmRows = dr
return dr
}
func newInnerRows(id int16, stmt *DmStatement, execInfo *execRetInfo) *innerRows {
rows := new(innerRows)
rows.id = id
rows.dmStmt = stmt
rows.columns = stmt.columns
rows.datas = execInfo.rsDatas
rows.totalRowCount = execInfo.updateCount
rows.isBdta = execInfo.rsBdta
rows.fetchSize = stmt.fetchSize
if len(execInfo.rsDatas) == 0 {
rows.sizeOfRow = 0
} else {
rows.sizeOfRow = execInfo.rsSizeof / len(execInfo.rsDatas)
}
rows.currentPos = -1
rows.datasOffset = -1
rows.datasStartPos = 0
rows.nextExecInfo = nil
rows.next = nil
if rows.dmStmt.rsMap != nil {
rows.dmStmt.rsMap[rows.id] = rows
}
if stmt.dmConn.dmConnector.enRsCache && execInfo.rsCacheOffset > 0 &&
int64(len(execInfo.rsDatas)) == execInfo.updateCount {
rp.put(stmt, stmt.nativeSql, execInfo)
}
return rows
}
func newLocalInnerRows(stmt *DmStatement, columns []column, rsDatas [][][]byte) *innerRows {
rows := new(innerRows)
rows.id = 0
rows.dmStmt = stmt
rows.fetchSize = stmt.fetchSize
if columns == nil {
rows.columns = make([]column, 0)
} else {
rows.columns = columns
}
if rsDatas == nil {
rows.datas = make([][][]byte, 0)
rows.totalRowCount = 0
} else {
rows.datas = rsDatas
rows.totalRowCount = int64(len(rsDatas))
}
rows.isBdta = false
return rows
}
func (innerRows *innerRows) checkIndex(index int) *column {
if index < 0 || index > len(innerRows.columns)-1 {
return nil
}
return &innerRows.columns[index]
}
func (innerRows *innerRows) fetchData(startPos int64) bool {
execInfo, err := innerRows.dmStmt.dmConn.Access.Dm_build_550(innerRows, startPos)
if err != nil {
return false
}
innerRows.totalRowCount = execInfo.updateCount
if execInfo.rsDatas != nil {
innerRows.datas = execInfo.rsDatas
innerRows.datasStartPos = startPos
innerRows.datasOffset = 0
return true
}
return false
}
func (innerRows *innerRows) getRowData(dest []driver.Value) (err error) {
for i, column := range innerRows.columns {
if i <= len(dest)-1 {
if column.colType == CURSOR {
var tmpExecInfo *execRetInfo
tmpExecInfo, err = innerRows.dmStmt.dmConn.Access.Dm_build_543(innerRows.dmStmt, 1)
if err != nil {
return err
}
if tmpExecInfo.hasResultSet {
dest[i] = newDmRows(newInnerRows(innerRows.id+1, innerRows.dmStmt, tmpExecInfo))
} else {
dest[i] = nil
}
continue
}
dest[i], err = column.getColumnData(innerRows.datas[innerRows.datasOffset][i+1], innerRows.dmStmt.dmConn)
innerRows.columns[i].isBdta = innerRows.isBdta
if err != nil {
return err
}
} else {
return nil
}
}
return nil
}
func (innerRows *innerRows) getRowCount() int64 {
innerRows.checkClosed()
if innerRows.totalRowCount == INT64_MAX {
return -1
}
return innerRows.totalRowCount
}
+1590
View File
File diff suppressed because it is too large Load Diff
+38
View File
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package util
func Split(s string, sep string) []string {
var foot = make([]int, len(s)) // 足够的元素个数
var count, sLen, sepLen = 0, len(s), len(sep)
for i := 0; i < sLen; i++ {
// 处理 s == “-9999-1" && seperators == "-"情况
if i == 0 && sLen >= sepLen {
if s[0:sepLen] == sep {
i += sepLen - 1
continue
}
}
for j := 0; j < sepLen; j++ {
if s[i] == sep[j] {
foot[count] = i
count++
break
}
}
}
var ret = make([]string, count+1)
if count == 0 {
ret[0] = s
return ret
}
ret[0] = s[0:foot[0]]
for i := 1; i < count; i++ {
ret[i] = s[foot[i-1]+1 : foot[i]]
}
ret[count] = s[foot[count-1]+1:]
return ret
}
+75
View File
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package util
import (
"go/build"
"os"
"runtime"
"strings"
)
const (
PathSeparator = string(os.PathSeparator)
PathListSeparator = string(os.PathListSeparator)
)
var (
goRoot = build.Default.GOROOT
goPath = build.Default.GOPATH //获取实际编译时的GOPATH值
)
type fileUtil struct {
}
var FileUtil = &fileUtil{}
func (fileUtil *fileUtil) Exists(path string) bool {
if _, err := os.Stat(path); !os.IsNotExist(err) {
return true
}
return false
}
func (fileUtil *fileUtil) Search(relativePath string) (path string) {
if strings.Contains(runtime.GOOS, "windows") {
relativePath = strings.ReplaceAll(relativePath, "/", "\\")
}
if fileUtil.Exists(goPath) {
for _, s := range strings.Split(goPath, PathListSeparator) {
path = s + PathSeparator + "src" + PathSeparator + relativePath
if fileUtil.Exists(path) {
return path
}
}
}
if fileUtil.Exists(goPath) {
for _, s := range strings.Split(goPath, PathListSeparator) {
path = s + PathSeparator + "pkg" + PathSeparator + relativePath
if fileUtil.Exists(path) {
return path
}
}
}
//if workDir, _ := os.Getwd(); fileUtil.Exists(workDir) {
// path = workDir + PathSeparator + "src" + PathSeparator + relativePath
// if fileUtil.Exists(path) {
// return path
// }
//}
//if fileUtil.Exists(goRoot) {
// path = goRoot + PathSeparator + "src" + PathSeparator + relativePath
// if fileUtil.Exists(path) {
// return path
// }
//}
return ""
}
+57
View File
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package util
const (
LINE_SEPARATOR = "\n"
)
// 执行f并忽略panic
func AbsorbPanic(f func()){
defer func() {
if p := recover(); p != nil {
// TODO do something
}
}()
f()
}
func SliceEquals(src []byte, dest []byte) bool {
if len(src) != len(dest) {
return false
}
for i, _ := range src {
if src[i] != dest[i] {
return false
}
}
return true
}
// 获取两个数的最大公约数,由调用者确保m、n>=0;如果m或n为0,返回1
func GCD(m int32, n int32) int32 {
if m == 0 || n == 0 {
return 1
}
r := m % n
m = n
n = r
if r == 0 {
return m
} else {
return GCD(m, n)
}
}
// 返回切片中所有数的累加值
func Sum(arr []int32) int32 {
var sum int32 = 0
for _, i := range arr {
sum += i
}
return sum
}
+264
View File
@@ -0,0 +1,264 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package util
import (
"bytes"
"runtime"
"strings"
"time"
"unicode"
)
type stringutil struct{}
var StringUtil = &stringutil{}
/*----------------------------------------------------*/
func (StringUtil *stringutil) LineSeparator() string {
var lineSeparator string
if strings.Contains(runtime.GOOS, "windows") {
lineSeparator = "\r\n"
} else if strings.Contains(runtime.GOOS, "mac") {
lineSeparator = "\r"
} else {
lineSeparator = "\n"
}
return lineSeparator
}
func (StringUtil *stringutil) Equals(str1 string, str2 string) bool {
return str1 == str2
}
func (StringUtil *stringutil) EqualsIgnoreCase(str1 string, str2 string) bool {
return strings.ToUpper(str1) == strings.ToUpper(str2)
}
func (StringUtil *stringutil) StartsWith(s string, subStr string) bool {
return strings.Index(s, subStr) == 0
}
func (StringUtil *stringutil) StartWithIgnoreCase(s string, subStr string) bool {
return strings.HasPrefix(strings.ToLower(s), strings.ToLower(subStr))
}
func (StringUtil *stringutil) EndsWith(s string, subStr string) bool {
return strings.LastIndex(s, subStr) == len(s)-1
}
func (StringUtil *stringutil) IsDigit(str string) bool {
if str == "" {
return false
}
sz := len(str)
for i := 0; i < sz; i++ {
if unicode.IsDigit(rune(str[i])) {
continue
} else {
return false
}
}
return true
}
func (StringUtil *stringutil) FormatDir(dir string) string {
dir = strings.TrimSpace(dir)
if dir != "" {
if !StringUtil.EndsWith(dir, PathSeparator) {
dir += PathSeparator
}
}
return dir
}
func (StringUtil *stringutil) HexStringToBytes(s string) []byte {
str := s
bs := make([]byte, 0)
flag := false
if strings.Index(str, "0x") == 0 || strings.Index(str, "0X") == 0 {
str = str[2:]
}
if len(str) == 0 {
return bs
}
var bsChr []byte
l := len(str)
if l%2 == 0 {
bsChr = []byte(str)
} else {
l += 1
bsChr = make([]byte, l)
bsChr[0] = '0'
for i := 0; i < l-1; i++ {
bsChr[i+1] = str[i]
}
}
bs = make([]byte, l/2)
pos := 0
for i := 0; i < len(bsChr); i += 2 {
bt := convertHex(bsChr[i])
bt2 := convertHex(bsChr[i+1])
if int(bt) == 0xff || int(bt2) == 0xff {
flag = true
break
}
bs[pos] = byte(bt*16 + bt2)
pos++
}
if flag {
bs = ([]byte)(str)
}
return bs
}
func convertHex(chr byte) byte {
if chr >= '0' && chr <= '9' {
return chr - '0'
} else if chr >= 'a' && chr <= 'f' {
return chr - 'a' + 10
} else if chr >= 'A' && chr <= 'F' {
return chr - 'A' + 10
} else {
return 0xff
}
}
func (StringUtil *stringutil) BytesToHexString(bs []byte, pre bool) string {
if bs == nil {
return ""
}
if len(bs) == 0 {
return ""
}
hexDigits := "0123456789ABCDEF"
ret := new(strings.Builder)
for _, b := range bs {
ret.WriteByte(hexDigits[0x0F&(b>>4)])
ret.WriteByte(hexDigits[0x0F&b])
}
if pre {
return "0x" + ret.String()
}
return ret.String()
}
func (StringUtil *stringutil) ProcessSingleQuoteOfName(name string) string {
return StringUtil.processQuoteOfName(name, "'")
}
func (StringUtil *stringutil) ProcessDoubleQuoteOfName(name string) string {
return StringUtil.processQuoteOfName(name, "\"")
}
func (StringUtil *stringutil) processQuoteOfName(name string, quote string) string {
if quote == "" || name == "" {
return name
}
temp := name
result := bytes.NewBufferString("")
index := -1
quetoLength := len(quote)
index = strings.Index(temp, quote)
for index != -1 {
result.WriteString(temp[:index+quetoLength])
result.WriteString(quote)
temp = temp[index+quetoLength:]
index = strings.Index(temp, quote)
}
result.WriteString(temp)
return result.String()
}
func (StringUtil *stringutil) FormatTime() string {
return time.Now().Format("2006-01-02 15:04:05")
}
func (StringUtil *stringutil) SubstringBetween(str string, open string, close string) string {
if str == "" {
return ""
}
iopen := -1
if open != "" {
iopen = strings.Index(str, open)
}
iclose := -1
if close != "" {
iclose = strings.LastIndex(str, close)
}
if iopen == -1 && iclose == -1 {
return ""
} else if iopen == -1 {
return str[0:iclose]
} else if iclose == -1 {
return str[iopen:]
} else {
return str[iopen:iclose]
}
}
//bug656976 在常量参数化时,将\+任意字符的两个字符解析成一个转义后字符,如:
// 字符串参数'a\nb'解析成字符串参数'a换行b'
func (StringUtil *stringutil) Translate(s string) string {
if !strings.ContainsRune(s, '\\') {
return s
}
reader := strings.NewReader(s)
trans := bytes.NewBufferString("")
for {
curRune, _, err := reader.ReadRune()
if err != nil {
break
}
if curRune != '\\' {
trans.WriteRune(curRune)
} else {
//转义规则参考mysql,'\'作为转义符必须消除,不管是否作为有真正含义的特殊字符,如\x也需要变化为x
nextRune, _, err := reader.ReadRune()
if err != nil {
break
}
switch nextRune {
case 'b':
trans.WriteRune('\b')
break
case 'f':
trans.WriteRune('\f')
break
case 'n':
trans.WriteRune('\n')
break
case 'r':
trans.WriteRune('\r')
break
case 't':
trans.WriteRune('\t')
break
default:
trans.WriteRune(nextRune)
break
}
}
}
return trans.String()
}
+142
View File
@@ -0,0 +1,142 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import "database/sql/driver"
type DmStruct struct {
TypeData
m_strctDesc *StructDescriptor // 结构体的描述信息
m_attribs []TypeData // 各属性值
m_objCount int // 一个数组项中存在对象类型的个数(class、动态数组)
m_strCount int // 一个数组项中存在字符串类型的个数
typeName string
elements []interface{}
// Valid为false代表DmArray数据在数据库中为NULL
Valid bool
}
// 数据库自定义类型Struct构造函数,typeName为库中定义的类型名称,elements为该类型每个字段的值
//
// 例如,自定义类型语句为:create or replace type myType as object (a1 int, a2 varchar);
//
// 则绑入绑出的go对象为: val := dm.NewDmStruct("myType", []interface{} {123, "abc"})
func NewDmStruct(typeName string, elements []interface{}) *DmStruct {
ds := new(DmStruct)
ds.typeName = typeName
ds.elements = elements
ds.Valid = true
return ds
}
func (ds *DmStruct) create(dc *DmConnection) (*DmStruct, error) {
desc, err := newStructDescriptor(ds.typeName, dc)
if err != nil {
return nil, err
}
return ds.createByStructDescriptor(desc, dc)
}
func newDmStructByTypeData(atData []TypeData, desc *TypeDescriptor) *DmStruct {
ds := new(DmStruct)
ds.Valid = true
ds.initTypeData()
ds.m_strctDesc = newStructDescriptorByTypeDescriptor(desc)
ds.m_attribs = atData
return ds
}
func (dest *DmStruct) Scan(src interface{}) error {
if dest == nil {
return ECGO_STORE_IN_NIL_POINTER.throw()
}
switch src := src.(type) {
case nil:
*dest = *new(DmStruct)
// 将Valid标志置false表示数据库中该列为NULL
(*dest).Valid = false
return nil
case *DmStruct:
*dest = *src
return nil
default:
return UNSUPPORTED_SCAN.throw()
}
}
func (dt DmStruct) Value() (driver.Value, error) {
if !dt.Valid {
return nil, nil
}
return dt, nil
}
func (ds *DmStruct) getAttribsTypeData() []TypeData {
return ds.m_attribs
}
func (ds *DmStruct) createByStructDescriptor(desc *StructDescriptor, conn *DmConnection) (*DmStruct, error) {
ds.initTypeData()
if nil == desc {
return nil, ECGO_INVALID_PARAMETER_VALUE.throw()
}
ds.m_strctDesc = desc
if nil == ds.elements {
ds.m_attribs = make([]TypeData, desc.getSize())
} else {
if desc.getSize() != len(ds.elements) && desc.getObjId() != 4 {
return nil, ECGO_STRUCT_MEM_NOT_MATCH.throw()
}
var err error
ds.m_attribs, err = TypeDataSV.toStruct(ds.elements, ds.m_strctDesc.m_typeDesc)
if err != nil {
return nil, err
}
}
return ds, nil
}
// 获取Struct对象在数据库中的类型名称
func (ds *DmStruct) GetSQLTypeName() (string, error) {
return ds.m_strctDesc.m_typeDesc.getFulName()
}
// 获取Struct对象中的各个字段的值
func (ds *DmStruct) GetAttributes() ([]interface{}, error) {
return TypeDataSV.toJavaArrayByDmStruct(ds)
}
func (ds *DmStruct) checkCol(col int) error {
if col < 1 || col > len(ds.m_attribs) {
return ECGO_INVALID_SEQUENCE_NUMBER.throw()
}
return nil
}
// 获取指定索引的成员变量值,以TypeData的形式给出,col 1 based
func (ds *DmStruct) getAttrValue(col int) (*TypeData, error) {
err := ds.checkCol(col)
if err != nil {
return nil, err
}
return &ds.m_attribs[col-1], nil
}
func (ds *DmStruct) checkValid() error {
if !ds.Valid {
return ECGO_IS_NULL.throw()
}
return nil
}
+233
View File
@@ -0,0 +1,233 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"database/sql/driver"
"strings"
"time"
)
const (
Seconds_1900_1970 = 2209017600
OFFSET_YEAR = 0
OFFSET_MONTH = 1
OFFSET_DAY = 2
OFFSET_HOUR = 3
OFFSET_MINUTE = 4
OFFSET_SECOND = 5
OFFSET_NANOSECOND = 6
OFFSET_TIMEZONE = 7
DT_LEN = 8
INVALID_VALUE = int(INT32_MIN)
NANOSECOND_DIGITS = 9
NANOSECOND_POW = 1000000000
)
type DmTimestamp struct {
dt []int
dtype int
scale int
oracleFormatPattern string
oracleDateLanguage int
// Valid为false代表DmArray数据在数据库中为NULL
Valid bool
}
func newDmTimestampFromDt(dt []int, dtype int, scale int) *DmTimestamp {
dmts := new(DmTimestamp)
dmts.Valid = true
dmts.dt = dt
dmts.dtype = dtype
dmts.scale = scale
return dmts
}
func newDmTimestampFromBytes(bytes []byte, column column, conn *DmConnection) *DmTimestamp {
dmts := new(DmTimestamp)
dmts.Valid = true
dmts.dt = decode(bytes, column.isBdta, column, int(conn.dmConnector.localTimezone), int(conn.DbTimezone))
if isLocalTimeZone(int(column.colType), int(column.scale)) {
dmts.scale = getLocalTimeZoneScale(int(column.colType), int(column.scale))
} else {
dmts.scale = int(column.scale)
}
dmts.dtype = int(column.colType)
dmts.scale = int(column.scale)
dmts.oracleDateLanguage = int(conn.OracleDateLanguage)
switch column.colType {
case DATE:
dmts.oracleFormatPattern = conn.FormatDate
case TIME:
dmts.oracleFormatPattern = conn.FormatTime
case TIME_TZ:
dmts.oracleFormatPattern = conn.FormatTimeTZ
case DATETIME, DATETIME2:
dmts.oracleFormatPattern = conn.FormatTimestamp
case DATETIME_TZ, DATETIME2_TZ:
dmts.oracleFormatPattern = conn.FormatTimestampTZ
}
return dmts
}
func NewDmTimestampFromString(str string) (*DmTimestamp, error) {
dt := make([]int, DT_LEN)
dtype, err := toDTFromString(strings.TrimSpace(str), dt)
if err != nil {
return nil, err
}
if dtype == DATE {
return newDmTimestampFromDt(dt, dtype, 0), nil
}
return newDmTimestampFromDt(dt, dtype, 6), nil
}
func NewDmTimestampFromTime(time time.Time) *DmTimestamp {
dt := toDTFromTime(time)
return newDmTimestampFromDt(dt, DATETIME, 6)
}
func (dmTimestamp *DmTimestamp) ToTime() time.Time {
_, tzs := time.Now().Zone()
return toTimeFromDT(dmTimestamp.dt, tzs / 60)
}
// 获取年月日时分秒毫秒时区
func (dmTimestamp *DmTimestamp) GetDt() []int {
return dmTimestamp.dt
}
func (dmTimestamp *DmTimestamp) CompareTo(ts DmTimestamp) int {
if dmTimestamp.ToTime().Equal(ts.ToTime()) {
return 0
} else if dmTimestamp.ToTime().Before(ts.ToTime()) {
return -1
} else {
return 1
}
}
func (dmTimestamp *DmTimestamp) String() string {
if dmTimestamp.oracleFormatPattern != "" {
return dtToStringByOracleFormat(dmTimestamp.dt, dmTimestamp.oracleFormatPattern, int32(dmTimestamp.scale), dmTimestamp.oracleDateLanguage)
}
return dtToString(dmTimestamp.dt, dmTimestamp.dtype, dmTimestamp.scale)
}
func (dest *DmTimestamp) Scan(src interface{}) error {
if dest == nil {
return ECGO_STORE_IN_NIL_POINTER.throw()
}
switch src := src.(type) {
case nil:
*dest = *new(DmTimestamp)
// 将Valid标志置false表示数据库中该列为NULL
(*dest).Valid = false
return nil
case *DmTimestamp:
*dest = *src
return nil
case time.Time:
ret := NewDmTimestampFromTime(src)
*dest = *ret
return nil
case string:
ret, err := NewDmTimestampFromString(src)
if err != nil {
return err
}
*dest = *ret
return nil
default:
return UNSUPPORTED_SCAN.throw()
}
}
func (dmTimestamp DmTimestamp) Value() (driver.Value, error) {
if !dmTimestamp.Valid {
return nil, nil
}
return dmTimestamp, nil
}
//func (dmTimestamp *DmTimestamp) toBytes() ([]byte, error) {
// return encode(dmTimestamp.dt, dmTimestamp.dtype, dmTimestamp.scale, dmTimestamp.dt[OFFSET_TIMEZONE])
//}
/**
* 获取当前对象的年月日时分秒,如果原来没有decode会先decode;
*/
func (dmTimestamp *DmTimestamp) getDt() []int {
return dmTimestamp.dt
}
func (dmTimestamp *DmTimestamp) getTime() int64 {
_, tzs := time.Now().Zone()
sec := toTimeFromDT(dmTimestamp.dt, tzs / 60).Unix()
return sec + int64(dmTimestamp.dt[OFFSET_NANOSECOND])
}
func (dmTimestamp *DmTimestamp) setTime(time int64) {
timeInMillis := (time / 1000) * 1000
nanos := (int64)((time % 1000) * 1000000)
if nanos < 0 {
nanos = 1000000000 + nanos
timeInMillis = (((time / 1000) - 1) * 1000)
}
dmTimestamp.dt = toDTFromUnix(timeInMillis, nanos)
}
func (dmTimestamp *DmTimestamp) setTimezone(tz int) error {
// DM中合法的时区取值范围为-12:59至+14:00
if tz <= -13*60 || tz > 14*60 {
return ECGO_INVALID_DATETIME_FORMAT.throw()
}
dmTimestamp.dt[OFFSET_TIMEZONE] = tz
return nil
}
func (dmTimestamp *DmTimestamp) getNano() int64 {
return int64(dmTimestamp.dt[OFFSET_NANOSECOND] * 1000)
}
func (dmTimestamp *DmTimestamp) setNano(nano int64) {
dmTimestamp.dt[OFFSET_NANOSECOND] = (int)(nano / 1000)
}
func (dmTimestamp *DmTimestamp) string() string {
if dmTimestamp.oracleFormatPattern != "" {
return dtToStringByOracleFormat(dmTimestamp.dt, dmTimestamp.oracleFormatPattern, int32(dmTimestamp.scale), dmTimestamp.oracleDateLanguage)
}
return dtToString(dmTimestamp.dt, dmTimestamp.dtype, dmTimestamp.scale)
}
func (dmTimestamp *DmTimestamp) checkValid() error {
if !dmTimestamp.Valid {
return ECGO_IS_NULL.throw()
}
return nil
}
/* for gorm v2 */
func (d *DmTimestamp) GormDataType() string {
return "TIMESTAMP"
}
+204
View File
@@ -0,0 +1,204 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"context"
"strconv"
"strings"
"sync"
"time"
)
const (
STATUS_VALID_TIME = 20 * time.Second // ms
// sort 值
SORT_SERVER_MODE_INVALID = -1 // 不允许连接的模式
SORT_SERVER_NOT_ALIVE = -2 // 站点无法连接
SORT_UNKNOWN = INT32_MAX // 站点还未连接过,模式未知
SORT_NORMAL = 30
SORT_PRIMARY = 20
SORT_STANDBY = 10
// OPEN>MOUNT>SUSPEND
SORT_OPEN = 3
SORT_MOUNT = 2
SORT_SUSPEND = 1
)
type ep struct {
host string
port int32
alive bool
statusRefreshTs int64 // 状态更新的时间点
serverMode int32
serverStatus int32
dscControl bool
sort int32
epSeqno int32
epStatus int32
lock sync.Mutex
}
func newEP(host string, port int32) *ep {
ep := new(ep)
ep.host = host
ep.port = port
ep.serverMode = -1
ep.serverStatus = -1
ep.sort = SORT_UNKNOWN
return ep
}
func (ep *ep) getSort(checkTime bool) int32 {
if checkTime {
if time.Now().UnixNano()-ep.statusRefreshTs < int64(STATUS_VALID_TIME) {
return ep.sort
} else {
return SORT_UNKNOWN
}
}
return ep.sort
}
func (ep *ep) calcSort(loginMode int32) int32 {
var sort int32 = 0
switch loginMode {
case LOGIN_MODE_PRIMARY_FIRST:
{
// 主机优先:PRIMARY>NORMAL>STANDBY
switch ep.serverMode {
case SERVER_MODE_NORMAL:
sort += SORT_NORMAL * 10
case SERVER_MODE_PRIMARY:
sort += SORT_PRIMARY * 100
case SERVER_MODE_STANDBY:
sort += SORT_STANDBY
}
}
case LOGIN_MODE_STANDBY_FIRST:
{
// STANDBY优先: STANDBY>PRIMARY>NORMAL
switch ep.serverMode {
case SERVER_MODE_NORMAL:
sort += SORT_NORMAL
case SERVER_MODE_PRIMARY:
sort += SORT_PRIMARY * 10
case SERVER_MODE_STANDBY:
sort += SORT_STANDBY * 100
}
}
case LOGIN_MODE_NORMAL_FIRST:
{
// NORMAL优先: NORMAL>PRIMARY>STANDBY
switch ep.serverMode {
case SERVER_MODE_STANDBY:
sort += SORT_STANDBY
case SERVER_MODE_PRIMARY:
sort += SORT_PRIMARY * 10
case SERVER_MODE_NORMAL:
sort += SORT_NORMAL * 100
}
}
case LOGIN_MODE_PRIMARY_ONLY:
if ep.serverMode != SERVER_MODE_PRIMARY {
return SORT_SERVER_MODE_INVALID
}
sort += SORT_PRIMARY
case LOGIN_MODE_STANDBY_ONLY:
if ep.serverMode != SERVER_MODE_STANDBY {
return SORT_SERVER_MODE_INVALID
}
sort += SORT_STANDBY
}
switch ep.serverStatus {
case SERVER_STATUS_MOUNT:
sort += SORT_MOUNT
case SERVER_STATUS_OPEN:
sort += SORT_OPEN
case SERVER_STATUS_SUSPEND:
sort += SORT_SUSPEND
}
return sort
}
func (ep *ep) refreshStatus(alive bool, conn *DmConnection) {
ep.lock.Lock()
defer ep.lock.Unlock()
ep.alive = alive
ep.statusRefreshTs = time.Now().UnixNano()
if alive {
ep.serverMode = conn.SvrMode
ep.serverStatus = conn.SvrStat
ep.dscControl = conn.dscControl
ep.sort = ep.calcSort(int32(conn.dmConnector.loginMode))
} else {
ep.serverMode = -1
ep.serverStatus = -1
ep.dscControl = false
ep.sort = SORT_SERVER_NOT_ALIVE
}
}
func (ep *ep) connect(connector *DmConnector) (*DmConnection, error) {
connector.host = ep.host
connector.port = ep.port
conn, err := connector.connectSingle(context.Background())
if err != nil {
ep.refreshStatus(false, conn)
return nil, err
}
ep.refreshStatus(true, conn)
return conn, nil
}
func (ep *ep) getServerStatusDesc(serverStatus int32) string {
ret := ""
switch ep.serverStatus {
case SERVER_STATUS_OPEN:
ret = "OPEN"
case SERVER_STATUS_MOUNT:
ret = "MOUNT"
case SERVER_STATUS_SUSPEND:
ret = "SUSPEND"
default:
ret = "UNKNOWN"
}
return ret
}
func (ep *ep) getServerModeDesc(serverMode int32) string {
ret := ""
switch ep.serverMode {
case SERVER_MODE_NORMAL:
ret = "NORMAL"
case SERVER_MODE_PRIMARY:
ret = "PRIMARY"
case SERVER_MODE_STANDBY:
ret = "STANDBY"
default:
ret = "UNKNOWN"
}
return ret
}
func (ep *ep) String() string {
dscControl := ")"
if ep.dscControl {
dscControl = ", DSC CONTROL)"
}
return strings.TrimSpace(ep.host) + ":" + strconv.Itoa(int(ep.port)) +
" (" + ep.getServerModeDesc(ep.serverMode) + ", " + ep.getServerStatusDesc(ep.serverStatus) + dscControl
}
+148
View File
@@ -0,0 +1,148 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"bytes"
"math/rand"
"sync"
"time"
"gitee.com/chunanyong/dm/util"
)
/**
* dm_svc.conf中配置的服务名对应的一组实例, 以及相关属性和状态信息
*
* 需求:
* 1. 连接均匀分布在各个节点上
* 2. loginModeloginStatus匹配
* 3. 连接异常节点比较耗时,在DB列表中包含异常节点时异常连接尽量靠后,减少对建连接速度的影响
*
*
* DB 连接顺序:
* 1. well distribution,每次连接都从列表的下一个节点开始
* 2. 用DB sort值按从大到小排序,sort为一个四位数XXXX,个位--serverStatus,十位--serverMode,共 有三种模式,最优先的 *100, 次优先的*10
*/
type epGroup struct {
name string
epList []*ep
props *Properties
epStartPos int32 // wellDistribute 起始位置
lock sync.Mutex
}
func newEPGroup(name string, serverList []*ep) *epGroup {
g := new(epGroup)
g.name = name
g.epList = serverList
if serverList == nil || len(serverList) == 0 {
g.epStartPos = -1
} else {
// 保证进程间均衡,起始位置采用随机值
g.epStartPos = rand.Int31n(int32(len(serverList))) - 1
}
return g
}
func (g *epGroup) connect(connector *DmConnector) (*DmConnection, error) {
var dbSelector = g.getEPSelector(connector)
var ex error = nil
// 如果配置了loginMode的主、备等优先策略,而未找到最高优先级的节点时持续循环switchtimes次,如果最终还是没有找到最高优先级则选择次优先级的
// 如果只有一个节点,无需switchTimes+1;多个节点时保证switchTimes轮尝试,最后一轮决定用哪个节点(由于节点已经按照模式优先级排序,最后一轮理论上就是连第一个节点)
var cycleCount int32
if len(g.epList) == 1 {
cycleCount = connector.switchTimes
} else {
cycleCount = connector.switchTimes + 1
}
for i := int32(0); i < cycleCount; i++ {
// 循环了一遍,如果没有符合要求的, 重新排序, 再尝试连接
conn, err := g.traverseServerList(connector, dbSelector, i == 0, i == cycleCount-1)
if err != nil {
ex = err
time.Sleep(time.Duration(connector.switchInterval) * time.Millisecond)
continue
}
return conn, nil
}
return nil, ex
}
func (g *epGroup) getEPSelector(connector *DmConnector) *epSelector {
if connector.epSelector == TYPE_HEAD_FIRST {
return newEPSelector(g.epList)
} else {
serverCount := int32(len(g.epList))
sortEPs := make([]*ep, serverCount)
g.lock.Lock()
defer g.lock.Unlock()
g.epStartPos = (g.epStartPos + 1) % serverCount
for i := int32(0); i < serverCount; i++ {
sortEPs[i] = g.epList[(i+g.epStartPos)%serverCount]
}
return newEPSelector(sortEPs)
}
}
/**
* 从指定编号开始,遍历一遍服务名中的ip列表,只连接指定类型(主机或备机)的ip
* @param servers
* @param checkTime
*
* @exception
* DBError.ECJDBC_INVALID_SERVER_MODE 有站点的模式不匹配
* DBError.ECJDBC_COMMUNITION_ERROR 所有站点都连不上
*/
func (g *epGroup) traverseServerList(connector *DmConnector, epSelector *epSelector, first bool, last bool) (*DmConnection, error) {
epList := epSelector.sortDBList(first)
errorMsg := bytes.NewBufferString("")
var ex error = nil // 第一个错误
for _, server := range epList {
conn, err := server.connect(connector)
if err != nil {
if ex == nil {
ex = err
}
errorMsg.WriteString("[")
errorMsg.WriteString(server.String())
errorMsg.WriteString("]")
errorMsg.WriteString(err.Error())
errorMsg.WriteString(util.StringUtil.LineSeparator())
continue
}
valid, err := epSelector.checkServerMode(conn, last)
if err != nil {
if ex == nil {
ex = err
}
errorMsg.WriteString("[")
errorMsg.WriteString(server.String())
errorMsg.WriteString("]")
errorMsg.WriteString(err.Error())
errorMsg.WriteString(util.StringUtil.LineSeparator())
continue
}
if !valid {
conn.close()
err = ECGO_INVALID_SERVER_MODE.throw()
if ex == nil {
ex = err
}
errorMsg.WriteString("[")
errorMsg.WriteString(server.String())
errorMsg.WriteString("]")
errorMsg.WriteString(err.Error())
errorMsg.WriteString(util.StringUtil.LineSeparator())
continue
}
return conn, nil
}
if ex != nil {
return nil, ex
}
return nil, ECGO_COMMUNITION_ERROR.addDetail(errorMsg.String()).throw()
}
+65
View File
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import "sort"
const (
TYPE_WELL_DISTRIBUTE = 0
TYPE_HEAD_FIRST = 1
)
type epSelector struct {
dbs []*ep
}
func newEPSelector(dbs []*ep) *epSelector {
return &epSelector{dbs}
}
func (s *epSelector) sortDBList(first bool) []*ep {
if !first {
// 按sort从大到小排序,相同sort值顺序不变
sort.Slice(s.dbs, func(i, j int) bool {
return s.dbs[i].getSort(first) > s.dbs[j].getSort(first)
})
}
return s.dbs
}
func (s *epSelector) checkServerMode(conn *DmConnection, last bool) (bool, error) {
// 只连dsc control节点
if conn.dmConnector.loginDscCtrl && !conn.dscControl {
conn.close()
return false, ECGO_INVALID_SERVER_MODE.throw()
}
// 模式不匹配, 这里使用的是连接之前的sort,连接之后server的状态可能发生改变sort也可能改变
if conn.dmConnector.loginStatus > 0 && int(conn.SvrStat) != conn.dmConnector.loginStatus {
conn.close()
return false, ECGO_INVALID_SERVER_MODE.throw()
}
if last {
switch conn.dmConnector.loginMode {
case LOGIN_MODE_PRIMARY_ONLY:
return conn.SvrMode == SERVER_MODE_PRIMARY, nil
case LOGIN_MODE_STANDBY_ONLY:
return conn.SvrMode == SERVER_MODE_STANDBY, nil
default:
return true, nil
}
}
switch conn.dmConnector.loginMode {
case LOGIN_MODE_NORMAL_FIRST:
return conn.SvrMode == SERVER_MODE_NORMAL, nil
case LOGIN_MODE_PRIMARY_FIRST, LOGIN_MODE_PRIMARY_ONLY:
return conn.SvrMode == SERVER_MODE_PRIMARY, nil
case LOGIN_MODE_STANDBY_FIRST, LOGIN_MODE_STANDBY_ONLY:
return conn.SvrMode == SERVER_MODE_STANDBY, nil
default:
break
}
return false, nil
}
+143
View File
@@ -0,0 +1,143 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"bytes"
"fmt"
"runtime"
"gitee.com/chunanyong/dm/i18n"
)
// 驱动级错误
var (
DSN_INVALID_SCHEMA = newDmError(9001, "error.dsn.invalidSchema")
UNSUPPORTED_SCAN = newDmError(9002, "error.unsupported.scan")
INVALID_PARAMETER_NUMBER = newDmError(9003, "error.invalidParameterNumber")
THIRD_PART_CIPHER_INIT_FAILED = newDmError(9004, "error.initThirdPartCipherFailed")
ECGO_NOT_QUERY_SQL = newDmError(9005, "error.notQuerySQL")
ECGO_NOT_EXEC_SQL = newDmError(9006, "error.notExecSQL")
ECGO_UNKOWN_NETWORK = newDmError(9007, "error.unkownNetWork")
ECGO_INVALID_CONN = newDmError(9008, "error.invalidConn")
ECGO_UNSUPPORTED_INPARAM_TYPE = newDmError(9009, "error.unsupportedInparamType")
ECGO_UNSUPPORTED_OUTPARAM_TYPE = newDmError(9010, "error.unsupportedOutparamType")
ECGO_STORE_IN_NIL_POINTER = newDmError(9011, "error.storeInNilPointer")
ECGO_IS_NULL = newDmError(9012, "error.isNull")
DSN_INVALID_FORMAT = newDmError(9001, "error.dsn.invalidFormat")
)
var (
ECGO_CONNECTION_SWITCH_FAILED = newDmError(20001, "error.connectionSwitchFailed")
ECGO_CONNECTION_SWITCHED = newDmError(20000, "error.connectionSwitched")
ECGO_COMMUNITION_ERROR = newDmError(6001, "error.communicationError")
ECGO_MSG_CHECK_ERROR = newDmError(6002, "error.msgCheckError")
ECGO_INVALID_TIME_INTERVAL = newDmError(6005, "error.invalidTimeInterval")
ECGO_UNSUPPORTED_TYPE = newDmError(6006, "error.unsupportedType")
ECGO_DATA_CONVERTION_ERROR = newDmError(6007, "error.dataConvertionError")
ECGO_INVALID_SQL_TYPE = newDmError(6009, "error.invalidSqlType")
ECGO_INVALID_DATETIME_FORMAT = newDmError(6015, "error.invalidDateTimeFormat")
ECGO_INVALID_COLUMN_TYPE = newDmError(6016, "error.invalidColumnType")
ECGO_RESULTSET_IS_READ_ONLY = newDmError(6029, "error.resultsetInReadOnlyStatus")
ECGO_INVALID_SEQUENCE_NUMBER = newDmError(6032, "error.invalidSequenceNumber")
ECGO_RESULTSET_CLOSED = newDmError(6034, "errorResultSetColsed")
ECGO_STATEMENT_HANDLE_CLOSED = newDmError(6035, "errorStatementHandleClosed")
ECGO_INVALID_PARAMETER_VALUE = newDmError(6036, "error.invalidParamterValue")
ECGO_INVALID_TRAN_ISOLATION = newDmError(6038, "error.invalidTranIsolation")
ECGO_COMMIT_IN_AUTOCOMMIT_MODE = newDmError(6039, "errorCommitInAutoCommitMode")
ECGO_ROLLBACK_IN_AUTOCOMMIT_MODE = newDmError(6040, "errorRollbackInAutoCommitMode")
ECGO_UNBINDED_PARAMETER = newDmError(6054, "error.unbindedParameter")
ECGO_PARAM_COUNT_LIMIT = newDmError(6056, "error.ParamCountLimit")
ECGO_INVALID_LENGTH_OR_OFFSET = newDmError(6057, "error.invalidLenOrOffset")
ECGO_CONNECTION_CLOSED = newDmError(6060, "error.error.connectionClosedOrNotBuild")
ECGO_INTERVAL_OVERFLOW = newDmError(6066, "error.intervalValueOverflow")
ECGO_STRING_CUT = newDmError(6067, "error.stringCut")
ECGO_INVALID_HEX = newDmError(6068, "error.invalidHex")
ECGO_INVALID_CIPHER = newDmError(6069, "error.invalidCipher")
ECGO_INVALID_BFILE_STR = newDmError(6070, "error.invalidBFile")
ECGO_OSAUTH_ERROR = newDmError(6073, "error.osauthError")
ECGO_ERROR_SERVER_VERSION = newDmError(6074, "error.serverVersion")
ECGO_USERNAME_TOO_LONG = newDmError(6075, "error.usernameTooLong")
ECGO_PASSWORD_TOO_LONG = newDmError(6076, "error.passwordTooLong")
ECGO_INVALID_COMPLEX_TYPE_NAME = newDmError(6079, "error.invalidComplexTypeName")
ECGO_STRUCT_MEM_NOT_MATCH = newDmError(6080, "error.structMemNotMatch")
ECGO_INVALID_OBJ_BLOB = newDmError(6081, "error.invalidObjBlob")
ECGO_INVALID_ARRAY_LEN = newDmError(6082, "error.invalidArrayLen")
ECGO_INVALID_SERVER_MODE = newDmError(6091, "error.invalidServerMode")
ECGO_DATA_TOO_LONG = newDmError(6092, "error.dataTooLong")
ECGO_BATCH_ERROR = newDmError(6093, "error.batchError")
ECGO_MSG_TOO_LONG = newDmError(6101, "error.msgTooLong")
ECGO_INVALID_DATETIME_VALUE = newDmError(6103, "error.invalidDateTimeValue")
ECGO_INIT_SSL_FAILED = newDmError(20002, "error.SSLInitFailed")
ECGO_LOB_FREED = newDmError(20003, "error.LobDataHasFreed")
ECGO_FATAL_ERROR = newDmError(20004, "error.fatalError")
)
// Svr Msg Err
var (
ECGO_DATA_OVERFLOW = newDmError(-6102, "error.dataOverflow")
ECGO_DATETIME_OVERFLOW = newDmError(-6112, "error.datetimeOverflow")
EC_RN_EXCEED_ROWSET_SIZE = newDmError(-7036, "")
EC_BP_WITH_ERROR = newDmError(121, "warning.bpWithErr")
)
type DmError struct {
ErrCode int32
ErrText string
stack []uintptr
detail string
}
func newDmError(errCode int32, errText string) *DmError {
de := new(DmError)
de.ErrCode = errCode
de.ErrText = errText
de.stack = nil
de.detail = ""
return de
}
func (dmError *DmError) throw() *DmError {
var pcs [32]uintptr
n := runtime.Callers(2, pcs[:])
dmError.stack = pcs[0:n]
return dmError
}
func (dmError *DmError) Stack() string {
if dmError == nil || dmError.stack == nil {
return ""
}
buffer := bytes.NewBuffer(nil)
index := 1
space := " "
for _, p := range dmError.stack {
if fn := runtime.FuncForPC(p - 1); fn != nil {
file, line := fn.FileLine(p - 1)
buffer.WriteString(fmt.Sprintf(" %d).%s%s\n \t%s:%d\n", index, space, fn.Name(), file, line))
index++
}
}
return buffer.String()
}
func (dmError *DmError) getErrText() string {
return i18n.Get(dmError.ErrText, Locale)
}
func (dmError *DmError) Error() string {
return fmt.Sprintf("Error %d: %s", dmError.ErrCode, dmError.getErrText()) + dmError.detail // + "\n" + "stack info:\n" + dmError.Stack()
}
// 扩充ErrText
func (dmError *DmError) addDetail(detail string) *DmError {
dmError.detail = detail
return dmError
}
func (dmError *DmError) addDetailln(detail string) *DmError {
return dmError.addDetail("\n" + detail)
}
+311
View File
@@ -0,0 +1,311 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
const (
PARAM_COUNT_LIMIT int32 = 65536
IGNORE_TARGET_LENGTH int32 = -1
IGNORE_TARGET_SCALE int32 = -1
IGNORE_TARGET_TYPE = INT32_MIN
TYPE_FLAG_UNKNOWN byte = 0 // 未知类型
TYPE_FLAG_EXACT byte = 1 // 精确类型
TYPE_FLAG_RECOMMEND byte = 2 // 推荐类型
IO_TYPE_UNKNOWN int8 = -1
IO_TYPE_IN int8 = 0
IO_TYPE_OUT int8 = 1
IO_TYPE_INOUT int8 = 2
MASK_ORACLE_DATE int32 = 1
MASK_ORACLE_FLOAT int32 = 2
MASK_BFILE int32 = 3
MASK_LOCAL_DATETIME int32 = 4
)
type execRetInfo struct {
// param
outParamDatas [][]byte
// rs
hasResultSet bool
rsDatas [][][]byte
rsSizeof int // 结果集数据占用多少空间,(消息中结果集起始位置到 rsCacheOffset
// 的空间大小,这和实际的rsDatas占用空间大小有一定出入,这里粗略估算,用于结果集缓存时的空间管理)
rsCacheOffset int32 // 缓存信息,在响应消息体中的偏移,0表示不存在,仅结果集缓存中可以用
rsBdta bool
rsUpdatable bool
rsRowIds []int64
// rs cache
tbIds []int32
tbTss []int64
// print
printLen int32
printMsg string
// explain
explain string
// 影响行数
updateCount int64 // Insert/Update/Delet影响行数, select结果集的总行数
updateCounts []int64 // 批量影响行数
// 键
rowid int64
lastInsertId int64
// other
retSqlType int16 // 执行返回的语句类型
execId int32
serverParams []parameter
nativeSQL string
}
type column struct {
typeName string
colType int32
prec int32
scale int32
name string
tableName string
schemaName string
nullable bool
identity bool
readonly bool // 是否只读
baseName string
// lob info
lob bool
lobTabId int32
lobColId int16
// 用于描述ARRAY、STRUCT类型的特有描述信息
typeDescriptor *TypeDescriptor
isBdta bool
mask int32
}
type parameter struct {
column
typeFlag byte
ioType int8
outJType int32
outScale int32
outObjectName string
cursorStmt *DmStatement
hasDefault bool
}
func (column *column) InitColumn() *column {
column.typeName = ""
column.colType = 0
column.prec = 0
column.scale = 0
column.name = ""
column.tableName = ""
column.schemaName = ""
column.nullable = false
column.identity = false
column.readonly = false
column.baseName = ""
// lob info
column.lob = false
column.lobTabId = 0
column.lobColId = 0
// 用于描述ARRAY、STRUCT类型的特有描述信息
column.typeDescriptor = nil
column.isBdta = false
return column
}
func (parameter *parameter) InitParameter() *parameter {
parameter.InitColumn()
parameter.typeFlag = TYPE_FLAG_UNKNOWN
parameter.ioType = IO_TYPE_UNKNOWN
parameter.outJType = IGNORE_TARGET_TYPE
parameter.outScale = IGNORE_TARGET_SCALE
parameter.outObjectName = ""
parameter.cursorStmt = nil
return parameter
}
func (parameter *parameter) resetType(colType int32) {
parameter.colType = colType
parameter.scale = 0
switch colType {
case BIT, BOOLEAN:
parameter.prec = BIT_PREC
case TINYINT:
parameter.prec = TINYINT_PREC
case SMALLINT:
parameter.prec = SMALLINT_PREC
case INT:
parameter.prec = INT_PREC
case BIGINT:
parameter.prec = BIGINT_PREC
case CHAR, VARCHAR, VARCHAR2:
parameter.prec = VARCHAR_PREC
case CLOB:
parameter.prec = CLOB_PREC
case BINARY, VARBINARY:
parameter.prec = VARBINARY_PREC
case BLOB:
parameter.prec = BLOB_PREC
case DATE:
parameter.prec = DATE_PREC
case TIME:
parameter.prec = TIME_PREC
parameter.scale = 6
case TIME_TZ:
parameter.prec = TIME_TZ_PREC
parameter.scale = 6
case DATETIME:
parameter.prec = DATETIME_PREC
parameter.scale = 6
case DATETIME_TZ:
parameter.prec = DATETIME_TZ_PREC
parameter.scale = 6
case DATETIME2:
parameter.prec = DATETIME2_PREC
parameter.scale = 9
case DATETIME2_TZ:
parameter.prec = DATETIME2_TZ_PREC
parameter.scale = 9
case REAL,DOUBLE,DECIMAL,INTERVAL_YM,INTERVAL_DT,ARRAY,CLASS,PLTYPE_RECORD,SARRAY:
parameter.prec = 0
case UNKNOWN, NULL:
// UNKNOWN 导致服务器断言 // setNull导致服务器报错“字符转换失败”
parameter.colType = VARCHAR
parameter.prec = VARCHAR_PREC
default:
}
}
func (execInfo *execRetInfo) union(other *execRetInfo, startRow int, count int) {
if count == 1 {
execInfo.updateCounts[startRow] = other.updateCount
} else if execInfo.updateCounts != nil && other.updateCounts != nil{
copy(execInfo.updateCounts[startRow:startRow+count], other.updateCounts[0:count])
}
if execInfo.outParamDatas != nil {
execInfo.outParamDatas = append(execInfo.outParamDatas, other.outParamDatas...)
}
}
func NewExceInfo() *execRetInfo {
execInfo := execRetInfo{}
execInfo.outParamDatas = nil
execInfo.hasResultSet = false
execInfo.rsDatas = nil
execInfo.rsSizeof = 0
execInfo.rsCacheOffset = 0
execInfo.rsBdta = false
execInfo.rsUpdatable = false
execInfo.rsRowIds = nil
execInfo.tbIds = nil
execInfo.tbTss = nil
execInfo.printLen = 0
execInfo.printMsg = ""
execInfo.explain = ""
execInfo.updateCount = 0
execInfo.updateCounts = nil
execInfo.rowid = -1
execInfo.lastInsertId = 0
// other
execInfo.retSqlType = -1 // 执行返回的语句类型
execInfo.execId = 0
return &execInfo
}
+444
View File
@@ -0,0 +1,444 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"context"
"database/sql/driver"
"reflect"
"sync"
"sync/atomic"
"time"
)
type filter interface {
DmDriverOpen(filterChain *filterChain, d *DmDriver, dsn string) (*DmConnection, error)
DmDriverOpenConnector(filterChain *filterChain, d *DmDriver, dsn string) (*DmConnector, error)
DmConnectorConnect(filterChain *filterChain, c *DmConnector, ctx context.Context) (*DmConnection, error)
DmConnectorDriver(filterChain *filterChain, c *DmConnector) *DmDriver
DmConnectionBegin(filterChain *filterChain, c *DmConnection) (*DmConnection, error)
DmConnectionBeginTx(filterChain *filterChain, c *DmConnection, ctx context.Context, opts driver.TxOptions) (*DmConnection, error)
DmConnectionCommit(filterChain *filterChain, c *DmConnection) error
DmConnectionRollback(filterChain *filterChain, c *DmConnection) error
DmConnectionClose(filterChain *filterChain, c *DmConnection) error
DmConnectionPing(filterChain *filterChain, c *DmConnection, ctx context.Context) error
DmConnectionExec(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (*DmResult, error)
DmConnectionExecContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmResult, error)
DmConnectionQuery(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (*DmRows, error)
DmConnectionQueryContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmRows, error)
DmConnectionPrepare(filterChain *filterChain, c *DmConnection, query string) (*DmStatement, error)
DmConnectionPrepareContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string) (*DmStatement, error)
DmConnectionResetSession(filterChain *filterChain, c *DmConnection, ctx context.Context) error
DmConnectionCheckNamedValue(filterChain *filterChain, c *DmConnection, nv *driver.NamedValue) error
DmStatementClose(filterChain *filterChain, s *DmStatement) error
DmStatementNumInput(filterChain *filterChain, s *DmStatement) int
DmStatementExec(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmResult, error)
DmStatementExecContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmResult, error)
DmStatementQuery(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmRows, error)
DmStatementQueryContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmRows, error)
DmStatementCheckNamedValue(filterChain *filterChain, s *DmStatement, nv *driver.NamedValue) error
DmResultLastInsertId(filterChain *filterChain, r *DmResult) (int64, error)
DmResultRowsAffected(filterChain *filterChain, r *DmResult) (int64, error)
DmRowsColumns(filterChain *filterChain, r *DmRows) []string
DmRowsClose(filterChain *filterChain, r *DmRows) error
DmRowsNext(filterChain *filterChain, r *DmRows, dest []driver.Value) error
DmRowsHasNextResultSet(filterChain *filterChain, r *DmRows) bool
DmRowsNextResultSet(filterChain *filterChain, r *DmRows) error
DmRowsColumnTypeScanType(filterChain *filterChain, r *DmRows, index int) reflect.Type
DmRowsColumnTypeDatabaseTypeName(filterChain *filterChain, r *DmRows, index int) string
DmRowsColumnTypeLength(filterChain *filterChain, r *DmRows, index int) (length int64, ok bool)
DmRowsColumnTypeNullable(filterChain *filterChain, r *DmRows, index int) (nullable, ok bool)
DmRowsColumnTypePrecisionScale(filterChain *filterChain, r *DmRows, index int) (precision, scale int64, ok bool)
}
type IDGenerator int64
var dmDriverIDGenerator = new(IDGenerator)
var dmConntorIDGenerator = new(IDGenerator)
var dmConnIDGenerator = new(IDGenerator)
var dmStmtIDGenerator = new(IDGenerator)
var dmResultIDGenerator = new(IDGenerator)
var dmRowsIDGenerator = new(IDGenerator)
func (g *IDGenerator) incrementAndGet() int64 {
return atomic.AddInt64((*int64)(g), 1)
}
type RWSiteEnum int
const (
PRIMARY RWSiteEnum = iota
STANDBY
ANYSITE
)
var (
goMapMu sync.RWMutex
goMap = make(map[string]goRun, 2)
)
type filterable struct {
filterChain *filterChain
rwInfo *rwInfo
logInfo *logInfo
recoverInfo *recoverInfo
statInfo *statInfo
objId int64
idGenerator *IDGenerator
}
func runLog() {
goMapMu.Lock()
_, ok := goMap["log"]
if !ok {
goMap["log"] = &logWriter{
flushQueue: make(chan []byte, LogFlushQueueSize),
date: time.Now().Format("2006-01-02"),
logFile: nil,
flushFreq: LogFlushFreq,
filePath: LogDir,
filePrefix: "dm_go",
buffer: Dm_build_4(),
}
go goMap["log"].doRun()
}
goMapMu.Unlock()
}
func runStat() {
goMapMu.Lock()
_, ok := goMap["stat"]
if !ok {
goMap["stat"] = newStatFlusher()
go goMap["stat"].doRun()
}
goMapMu.Unlock()
}
func (f *filterable) createFilterChain(bc *DmConnector, props *Properties) {
var filters = make([]filter, 0, 5)
if bc != nil {
if LogLevel != LOG_OFF {
filters = append(filters, &logFilter{})
f.logInfo = &logInfo{logRecord: new(LogRecord)}
runLog()
}
if StatEnable {
filters = append(filters, &statFilter{})
f.statInfo = newStatInfo()
goStatMu.Lock()
if goStat == nil {
goStat = newGoStat(1000)
}
goStatMu.Unlock()
runStat()
}
if bc.doSwitch != DO_SWITCH_OFF {
filters = append(filters, &reconnectFilter{})
f.recoverInfo = newRecoverInfo()
}
if bc.rwSeparate > RW_SEPARATE_OFF {
filters = append(filters, &rwFilter{})
f.rwInfo = newRwInfo()
}
} else if props != nil {
if ParseLogLevel(props) != LOG_OFF {
filters = append(filters, &logFilter{})
f.logInfo = &logInfo{logRecord: new(LogRecord)}
runLog()
}
if props.GetBool("statEnable", StatEnable) {
filters = append(filters, &statFilter{})
f.statInfo = newStatInfo()
goStatMu.Lock()
if goStat == nil {
goStat = newGoStat(1000)
}
goStatMu.Unlock()
runStat()
}
if props.GetInt(DoSwitchKey, int(DO_SWITCH_OFF), 0, 2) != int(DO_SWITCH_OFF) {
filters = append(filters, &reconnectFilter{})
f.recoverInfo = newRecoverInfo()
}
if props.GetBool("rwSeparate", false) {
filters = append(filters, &rwFilter{})
f.rwInfo = newRwInfo()
}
}
f.filterChain = newFilterChain(filters)
}
func (f *filterable) resetFilterable(src *filterable) {
f.filterChain = src.filterChain
f.logInfo = src.logInfo
f.rwInfo = src.rwInfo
f.statInfo = src.statInfo
}
func (f *filterable) getID() int64 {
if f.objId < 0 {
f.objId = f.idGenerator.incrementAndGet()
}
return f.objId
}
type logInfo struct {
logRecord *LogRecord
lastExecuteStartNano time.Time
}
type rwInfo struct {
distribute RWSiteEnum
rwCounter *rwCounter
connStandby *DmConnection
connCurrent *DmConnection
tryRecoverTs int64
stmtStandby *DmStatement
stmtCurrent *DmStatement
readOnly bool
}
func newRwInfo() *rwInfo {
rwInfo := new(rwInfo)
rwInfo.distribute = PRIMARY
rwInfo.readOnly = true
return rwInfo
}
func (rwi *rwInfo) cleanup() {
rwi.distribute = PRIMARY
rwi.rwCounter = nil
rwi.connStandby = nil
rwi.connCurrent = nil
rwi.stmtStandby = nil
rwi.stmtCurrent = nil
}
func (rwi *rwInfo) toPrimary() RWSiteEnum {
if rwi.distribute != PRIMARY {
rwi.rwCounter.countPrimary()
}
rwi.distribute = PRIMARY
return rwi.distribute
}
func (rwi *rwInfo) toAny() RWSiteEnum {
rwi.distribute = rwi.rwCounter.count(ANYSITE, rwi.connStandby)
return rwi.distribute
}
type recoverInfo struct {
checkEpRecoverTs int64
}
func newRecoverInfo() *recoverInfo {
recoverInfo := new(recoverInfo)
recoverInfo.checkEpRecoverTs = 0
return recoverInfo
}
type statInfo struct {
constructNano int64
connStat *connectionStat
lastExecuteStartNano int64
lastExecuteTimeNano int64
lastExecuteType ExecuteTypeEnum
firstResultSet bool
lastExecuteSql string
sqlStat *sqlStat
sql string
cursorIndex int
closeCount int
readStringLength int64
readBytesLength int64
openInputStreamCount int
openReaderCount int
}
var (
goStatMu sync.RWMutex
goStat *GoStat
)
func newStatInfo() *statInfo {
si := new(statInfo)
return si
}
func (si *statInfo) init(conn *DmConnection) {
si.connStat = goStat.createConnStat(conn)
}
func (si *statInfo) setConstructNano() {
si.constructNano = time.Now().UnixNano()
}
func (si *statInfo) getConstructNano() int64 {
return si.constructNano
}
func (si *statInfo) getConnStat() *connectionStat {
return si.connStat
}
func (si *statInfo) getLastExecuteStartNano() int64 {
return si.lastExecuteStartNano
}
func (si *statInfo) setLastExecuteStartNano(lastExecuteStartNano int64) {
si.lastExecuteStartNano = lastExecuteStartNano
}
func (si *statInfo) getLastExecuteTimeNano() int64 {
return si.lastExecuteTimeNano
}
func (si *statInfo) setLastExecuteTimeNano(lastExecuteTimeNano int64) {
si.lastExecuteTimeNano = lastExecuteTimeNano
}
func (si *statInfo) getLastExecuteType() ExecuteTypeEnum {
return si.lastExecuteType
}
func (si *statInfo) setLastExecuteType(lastExecuteType ExecuteTypeEnum) {
si.lastExecuteType = lastExecuteType
}
func (si *statInfo) isFirstResultSet() bool {
return si.firstResultSet
}
func (si *statInfo) setFirstResultSet(firstResultSet bool) {
si.firstResultSet = firstResultSet
}
func (si *statInfo) getLastExecuteSql() string {
return si.lastExecuteSql
}
func (si *statInfo) setLastExecuteSql(lastExecuteSql string) {
si.lastExecuteSql = lastExecuteSql
}
func (si *statInfo) getSqlStat() *sqlStat {
return si.sqlStat
}
func (si *statInfo) setSqlStat(sqlStat *sqlStat) {
si.sqlStat = sqlStat
}
func (si *statInfo) setConnStat(connStat *connectionStat) {
si.connStat = connStat
}
func (si *statInfo) setConstructNanoWithConstructNano(constructNano int64) {
si.constructNano = constructNano
}
func (si *statInfo) afterExecute(nanoSpan int64) {
si.lastExecuteTimeNano = nanoSpan
}
func (si *statInfo) beforeExecute() {
si.lastExecuteStartNano = time.Now().UnixNano()
}
func (si *statInfo) getSql() string {
return si.sql
}
func (si *statInfo) setSql(sql string) {
si.sql = sql
}
func (si *statInfo) getCursorIndex() int {
return si.cursorIndex
}
func (si *statInfo) setCursorIndex(cursorIndex int) {
si.cursorIndex = cursorIndex
}
func (si *statInfo) getCloseCount() int {
return si.closeCount
}
func (si *statInfo) setCloseCount(closeCount int) {
si.closeCount = closeCount
}
func (si *statInfo) getReadStringLength() int64 {
return si.readStringLength
}
func (si *statInfo) setReadStringLength(readStringLength int64) {
si.readStringLength = readStringLength
}
func (si *statInfo) getReadBytesLength() int64 {
return si.readBytesLength
}
func (si *statInfo) setReadBytesLength(readBytesLength int64) {
si.readBytesLength = readBytesLength
}
func (si *statInfo) getOpenInputStreamCount() int {
return si.openInputStreamCount
}
func (si *statInfo) setOpenInputStreamCount(openInputStreamCount int) {
si.openInputStreamCount = openInputStreamCount
}
func (si *statInfo) getOpenReaderCount() int {
return si.openReaderCount
}
func (si *statInfo) setOpenReaderCount(openReaderCount int) {
si.openReaderCount = openReaderCount
}
func (si *statInfo) incrementCloseCount() {
si.closeCount++
}
+403
View File
@@ -0,0 +1,403 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"context"
"database/sql/driver"
"reflect"
)
type filterChain struct {
filters []filter
fpos int
}
func newFilterChain(filters []filter) *filterChain {
fc := new(filterChain)
fc.filters = filters
fc.fpos = 0
return fc
}
func (filterChain *filterChain) reset() *filterChain {
filterChain.fpos = 0
return filterChain
}
func (filterChain *filterChain) DmDriverOpen(d *DmDriver, dsn string) (*DmConnection, error) {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmDriverOpen(filterChain, d, dsn)
}
return d.open(dsn)
}
func (filterChain *filterChain) DmDriverOpenConnector(d *DmDriver, dsn string) (*DmConnector, error) {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmDriverOpenConnector(filterChain, d, dsn)
}
return d.openConnector(dsn)
}
//DmConnector
func (filterChain *filterChain) DmConnectorConnect(c *DmConnector, ctx context.Context) (*DmConnection, error) {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmConnectorConnect(filterChain, c, ctx)
}
return c.connect(ctx)
}
func (filterChain *filterChain) DmConnectorDriver(c *DmConnector) *DmDriver {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmConnectorDriver(filterChain, c)
}
return c.driver()
}
//DmConnection
func (filterChain *filterChain) DmConnectionBegin(c *DmConnection) (*DmConnection, error) {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmConnectionBegin(filterChain, c)
}
return c.begin()
}
func (filterChain *filterChain) DmConnectionBeginTx(c *DmConnection, ctx context.Context, opts driver.TxOptions) (*DmConnection, error) {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmConnectionBeginTx(filterChain, c, ctx, opts)
}
return c.beginTx(ctx, opts)
}
func (filterChain *filterChain) DmConnectionCommit(c *DmConnection) error {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmConnectionCommit(filterChain, c)
}
return c.commit()
}
func (filterChain *filterChain) DmConnectionRollback(c *DmConnection) error {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmConnectionRollback(filterChain, c)
}
return c.rollback()
}
func (filterChain *filterChain) DmConnectionClose(c *DmConnection) error {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmConnectionClose(filterChain, c)
}
return c.close()
}
func (filterChain *filterChain) DmConnectionPing(c *DmConnection, ctx context.Context) error {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmConnectionPing(filterChain, c, ctx)
}
return c.ping(ctx)
}
func (filterChain *filterChain) DmConnectionExec(c *DmConnection, query string, args []driver.Value) (*DmResult, error) {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmConnectionExec(filterChain, c, query, args)
}
return c.exec(query, args)
}
func (filterChain *filterChain) DmConnectionExecContext(c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmResult, error) {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmConnectionExecContext(filterChain, c, ctx, query, args)
}
return c.execContext(ctx, query, args)
}
func (filterChain *filterChain) DmConnectionQuery(c *DmConnection, query string, args []driver.Value) (*DmRows, error) {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmConnectionQuery(filterChain, c, query, args)
}
return c.query(query, args)
}
func (filterChain *filterChain) DmConnectionQueryContext(c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmRows, error) {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmConnectionQueryContext(filterChain, c, ctx, query, args)
}
return c.queryContext(ctx, query, args)
}
func (filterChain *filterChain) DmConnectionPrepare(c *DmConnection, query string) (*DmStatement, error) {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmConnectionPrepare(filterChain, c, query)
}
return c.prepare(query)
}
func (filterChain *filterChain) DmConnectionPrepareContext(c *DmConnection, ctx context.Context, query string) (*DmStatement, error) {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmConnectionPrepareContext(filterChain, c, ctx, query)
}
return c.prepareContext(ctx, query)
}
func (filterChain *filterChain) DmConnectionResetSession(c *DmConnection, ctx context.Context) error {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmConnectionResetSession(filterChain, c, ctx)
}
return c.resetSession(ctx)
}
func (filterChain *filterChain) DmConnectionCheckNamedValue(c *DmConnection, nv *driver.NamedValue) error {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmConnectionCheckNamedValue(filterChain, c, nv)
}
return c.checkNamedValue(nv)
}
//DmStatement
func (filterChain *filterChain) DmStatementClose(s *DmStatement) error {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmStatementClose(filterChain, s)
}
return s.close()
}
func (filterChain *filterChain) DmStatementNumInput(s *DmStatement) int {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmStatementNumInput(filterChain, s)
}
return s.numInput()
}
func (filterChain *filterChain) DmStatementExec(s *DmStatement, args []driver.Value) (*DmResult, error) {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmStatementExec(filterChain, s, args)
}
return s.exec(args)
}
func (filterChain *filterChain) DmStatementExecContext(s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmResult, error) {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmStatementExecContext(filterChain, s, ctx, args)
}
return s.execContext(ctx, args)
}
func (filterChain *filterChain) DmStatementQuery(s *DmStatement, args []driver.Value) (*DmRows, error) {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmStatementQuery(filterChain, s, args)
}
return s.query(args)
}
func (filterChain *filterChain) DmStatementQueryContext(s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmRows, error) {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmStatementQueryContext(filterChain, s, ctx, args)
}
return s.queryContext(ctx, args)
}
func (filterChain *filterChain) DmStatementCheckNamedValue(s *DmStatement, nv *driver.NamedValue) error {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmStatementCheckNamedValue(filterChain, s, nv)
}
return s.checkNamedValue(nv)
}
//DmResult
func (filterChain *filterChain) DmResultLastInsertId(r *DmResult) (int64, error) {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmResultLastInsertId(filterChain, r)
}
return r.lastInsertId()
}
func (filterChain *filterChain) DmResultRowsAffected(r *DmResult) (int64, error) {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmResultRowsAffected(filterChain, r)
}
return r.rowsAffected()
}
//DmRows
func (filterChain *filterChain) DmRowsColumns(r *DmRows) []string {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmRowsColumns(filterChain, r)
}
return r.columns()
}
func (filterChain *filterChain) DmRowsClose(r *DmRows) error {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmRowsClose(filterChain, r)
}
return r.close()
}
func (filterChain *filterChain) DmRowsNext(r *DmRows, dest []driver.Value) error {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmRowsNext(filterChain, r, dest)
}
return r.next(dest)
}
func (filterChain *filterChain) DmRowsHasNextResultSet(r *DmRows) bool {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmRowsHasNextResultSet(filterChain, r)
}
return r.hasNextResultSet()
}
func (filterChain *filterChain) DmRowsNextResultSet(r *DmRows) error {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmRowsNextResultSet(filterChain, r)
}
return r.nextResultSet()
}
func (filterChain *filterChain) DmRowsColumnTypeScanType(r *DmRows, index int) reflect.Type {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmRowsColumnTypeScanType(filterChain, r, index)
}
return r.columnTypeScanType(index)
}
func (filterChain *filterChain) DmRowsColumnTypeDatabaseTypeName(r *DmRows, index int) string {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmRowsColumnTypeDatabaseTypeName(filterChain, r, index)
}
return r.columnTypeDatabaseTypeName(index)
}
func (filterChain *filterChain) DmRowsColumnTypeLength(r *DmRows, index int) (length int64, ok bool) {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmRowsColumnTypeLength(filterChain, r, index)
}
return r.columnTypeLength(index)
}
func (filterChain *filterChain) DmRowsColumnTypeNullable(r *DmRows, index int) (nullable, ok bool) {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmRowsColumnTypeNullable(filterChain, r, index)
}
return r.columnTypeNullable(index)
}
func (filterChain *filterChain) DmRowsColumnTypePrecisionScale(r *DmRows, index int) (precision, scale int64, ok bool) {
if filterChain.fpos < len(filterChain.filters) {
f := filterChain.filters[filterChain.fpos]
filterChain.fpos++
return f.DmRowsColumnTypePrecisionScale(filterChain, r, index)
}
return r.columnTypePrecisionScale(index)
}
+907
View File
@@ -0,0 +1,907 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"context"
"database/sql/driver"
"fmt"
"io"
"reflect"
"strconv"
"time"
"gitee.com/chunanyong/dm/util"
)
type logFilter struct{}
func (filter *logFilter) DmDriverOpen(filterChain *filterChain, d *DmDriver, dsn string) (ret *DmConnection, err error) {
var logRecord = d.logInfo.logRecord.Reset()
logRecord.Set(d, "open", dsn)
defer func() {
filter.doLog(logRecord)
}()
ret, err = filterChain.DmDriverOpen(d, dsn)
if err != nil {
logRecord.SetError(err)
return
}
logRecord.SetReturnValue(ret)
return
}
func (filter *logFilter) DmDriverOpenConnector(filterChain *filterChain, d *DmDriver, dsn string) (ret *DmConnector, err error) {
var logRecord = d.logInfo.logRecord.Reset()
logRecord.Set(d, "openConnector", dsn)
defer func() {
filter.doLog(logRecord)
}()
ret, err = filterChain.DmDriverOpenConnector(d, dsn)
if err != nil {
logRecord.SetError(err)
return
}
logRecord.SetReturnValue(ret)
return
}
func (filter *logFilter) DmConnectorConnect(filterChain *filterChain, c *DmConnector, ctx context.Context) (ret *DmConnection, err error) {
var logRecord = c.logInfo.logRecord.Reset()
logRecord.Set(c, "connect")
defer func() {
filter.doLog(logRecord)
}()
ret, err = filterChain.DmConnectorConnect(c, ctx)
if err != nil {
logRecord.SetError(err)
return
}
logRecord.SetReturnValue(ret)
return
}
func (filter *logFilter) DmConnectorDriver(filterChain *filterChain, c *DmConnector) (ret *DmDriver) {
var logRecord = c.logInfo.logRecord.Reset()
logRecord.Set(c, "driver")
defer func() {
filter.doLog(logRecord)
}()
ret = filterChain.DmConnectorDriver(c)
logRecord.SetReturnValue(ret)
return
}
func (filter *logFilter) DmConnectionBegin(filterChain *filterChain, c *DmConnection) (ret *DmConnection, err error) {
var logRecord = c.logInfo.logRecord.Reset()
logRecord.Set(c, "begin")
defer func() {
filter.doLog(logRecord)
}()
ret, err = filterChain.DmConnectionBegin(c)
if err != nil {
logRecord.SetError(err)
return
}
logRecord.SetReturnValue(ret)
return
}
func (filter *logFilter) DmConnectionBeginTx(filterChain *filterChain, c *DmConnection, ctx context.Context, opts driver.TxOptions) (ret *DmConnection, err error) {
var logRecord = c.logInfo.logRecord.Reset()
logRecord.Set(c, "beginTx", opts)
defer func() {
filter.doLog(logRecord)
}()
ret, err = filterChain.DmConnectionBeginTx(c, ctx, opts)
if err != nil {
logRecord.SetError(err)
return
}
logRecord.SetReturnValue(ret)
return
}
func (filter *logFilter) DmConnectionCommit(filterChain *filterChain, c *DmConnection) (err error) {
var logRecord = c.logInfo.logRecord.Reset()
logRecord.Set(c, "commit")
defer func() {
filter.doLog(logRecord)
}()
err = filterChain.DmConnectionCommit(c)
if err != nil {
logRecord.SetError(err)
return
}
return
}
func (filter *logFilter) DmConnectionRollback(filterChain *filterChain, c *DmConnection) (err error) {
var logRecord = c.logInfo.logRecord.Reset()
logRecord.Set(c, "rollback")
defer func() {
filter.doLog(logRecord)
}()
err = filterChain.DmConnectionRollback(c)
if err != nil {
logRecord.SetError(err)
return
}
return
}
func (filter *logFilter) DmConnectionClose(filterChain *filterChain, c *DmConnection) (err error) {
var logRecord = c.logInfo.logRecord.Reset()
logRecord.Set(c, "close")
defer func() {
filter.doLog(logRecord)
}()
err = filterChain.DmConnectionClose(c)
if err != nil {
logRecord.SetError(err)
return
}
return
}
func (filter *logFilter) DmConnectionPing(filterChain *filterChain, c *DmConnection, ctx context.Context) (err error) {
var logRecord = c.logInfo.logRecord.Reset()
logRecord.Set(c, "ping")
defer func() {
filter.doLog(logRecord)
}()
err = filterChain.DmConnectionPing(c, ctx)
if err != nil {
logRecord.SetError(err)
return
}
return
}
func (filter *logFilter) DmConnectionExec(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (ret *DmResult, err error) {
var logRecord = c.logInfo.logRecord.Reset()
logRecord.Set(c, "exec", convertParams2(args)...)
defer func() {
filter.executeAfter(c.logInfo, logRecord)
filter.doLog(logRecord)
}()
logRecord.SetSql(query, true)
filter.executeBefore(c.logInfo)
ret, err = filterChain.DmConnectionExec(c, query, args)
if err != nil {
logRecord.SetError(err)
return
}
logRecord.SetReturnValue(ret)
return
}
func (filter *logFilter) DmConnectionExecContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (ret *DmResult, err error) {
var logRecord = c.logInfo.logRecord.Reset()
logRecord.Set(c, "execCtx", convertParams1(args)...)
defer func() {
filter.executeAfter(c.logInfo, logRecord)
filter.doLog(logRecord)
}()
logRecord.SetSql(query, true)
filter.executeBefore(c.logInfo)
ret, err = filterChain.DmConnectionExecContext(c, ctx, query, args)
if err != nil {
logRecord.SetError(err)
return
}
logRecord.SetReturnValue(ret)
return
}
func (filter *logFilter) DmConnectionQuery(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (ret *DmRows, err error) {
var logRecord = c.logInfo.logRecord.Reset()
logRecord.Set(c, "query", convertParams2(args)...)
defer func() {
filter.executeAfter(c.logInfo, logRecord)
filter.doLog(logRecord)
}()
logRecord.SetSql(query, true)
filter.executeBefore(c.logInfo)
ret, err = filterChain.DmConnectionQuery(c, query, args)
if err != nil {
logRecord.SetError(err)
return
}
logRecord.SetReturnValue(ret)
return
}
func (filter *logFilter) DmConnectionQueryContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (ret *DmRows, err error) {
var logRecord = c.logInfo.logRecord.Reset()
logRecord.Set(c, "queryCtx", convertParams1(args)...)
defer func() {
filter.executeAfter(c.logInfo, logRecord)
filter.doLog(logRecord)
}()
logRecord.SetSql(query, true)
filter.executeBefore(c.logInfo)
ret, err = filterChain.DmConnectionQueryContext(c, ctx, query, args)
if err != nil {
logRecord.SetError(err)
return
}
logRecord.SetReturnValue(ret)
return
}
func (filter *logFilter) DmConnectionPrepare(filterChain *filterChain, c *DmConnection, query string) (ret *DmStatement, err error) {
var logRecord = c.logInfo.logRecord.Reset()
logRecord.Set(c, "prepare", query)
defer func() {
filter.doLog(logRecord)
}()
logRecord.SetSql(query, false)
ret, err = filterChain.DmConnectionPrepare(c, query)
if err != nil {
logRecord.SetError(err)
return
}
logRecord.SetReturnValue(ret)
return
}
func (filter *logFilter) DmConnectionPrepareContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string) (ret *DmStatement, err error) {
var logRecord = c.logInfo.logRecord.Reset()
logRecord.Set(c, "prepareCtx", query)
defer func() {
filter.doLog(logRecord)
}()
logRecord.SetSql(query, false)
ret, err = filterChain.DmConnectionPrepareContext(c, ctx, query)
if err != nil {
logRecord.SetError(err)
return
}
logRecord.SetReturnValue(ret)
return
}
func (filter *logFilter) DmConnectionResetSession(filterChain *filterChain, c *DmConnection, ctx context.Context) (err error) {
var logRecord = c.logInfo.logRecord.Reset()
logRecord.Set(c, "resetSession")
defer func() {
filter.doLog(logRecord)
}()
err = filterChain.DmConnectionResetSession(c, ctx)
if err != nil {
logRecord.SetError(err)
return
}
return
}
func (filter *logFilter) DmConnectionCheckNamedValue(filterChain *filterChain, c *DmConnection, nv *driver.NamedValue) (err error) {
var logRecord = c.logInfo.logRecord.Reset()
logRecord.Set(c, "checkNamedValue", nv.Value)
defer func() {
filter.doLog(logRecord)
}()
err = filterChain.DmConnectionCheckNamedValue(c, nv)
if err != nil {
logRecord.SetError(err)
return
}
return
}
func (filter *logFilter) DmStatementClose(filterChain *filterChain, s *DmStatement) (err error) {
var logRecord = s.logInfo.logRecord.Reset()
logRecord.Set(s, "close")
defer func() {
filter.doLog(logRecord)
}()
err = filterChain.DmStatementClose(s)
if err != nil {
logRecord.SetError(err)
return
}
return
}
func (filter *logFilter) DmStatementNumInput(filterChain *filterChain, s *DmStatement) (ret int) {
var logRecord = s.logInfo.logRecord.Reset()
logRecord.Set(s, "numInput")
defer func() {
filter.doLog(logRecord)
}()
ret = filterChain.DmStatementNumInput(s)
logRecord.SetReturnValue(ret)
return
}
func (filter *logFilter) DmStatementExec(filterChain *filterChain, s *DmStatement, args []driver.Value) (ret *DmResult, err error) {
var logRecord = s.logInfo.logRecord.Reset()
logRecord.Set(s, "exec", convertParams2(args)...)
defer func() {
filter.executeAfter(s.logInfo, logRecord)
filter.doLog(logRecord)
}()
logRecord.SetSql(s.nativeSql, true)
filter.executeBefore(s.logInfo)
ret, err = filterChain.DmStatementExec(s, args)
if err != nil {
logRecord.SetError(err)
return
}
logRecord.SetReturnValue(ret)
return
}
func (filter *logFilter) DmStatementExecContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (ret *DmResult, err error) {
var logRecord = s.logInfo.logRecord.Reset()
logRecord.Set(s, "execCtx", convertParams1(args)...)
defer func() {
filter.executeAfter(s.logInfo, logRecord)
filter.doLog(logRecord)
}()
logRecord.SetSql(s.nativeSql, true)
filter.executeBefore(s.logInfo)
ret, err = filterChain.DmStatementExecContext(s, ctx, args)
if err != nil {
logRecord.SetError(err)
return
}
logRecord.SetReturnValue(ret)
return
}
func (filter *logFilter) DmStatementQuery(filterChain *filterChain, s *DmStatement, args []driver.Value) (ret *DmRows, err error) {
var logRecord = s.logInfo.logRecord.Reset()
logRecord.Set(s, "query", convertParams2(args)...)
defer func() {
filter.executeAfter(s.logInfo, logRecord)
filter.doLog(logRecord)
}()
logRecord.SetSql(s.nativeSql, true)
filter.executeBefore(s.logInfo)
ret, err = filterChain.DmStatementQuery(s, args)
if err != nil {
logRecord.SetError(err)
return
}
logRecord.SetReturnValue(ret)
return
}
func (filter *logFilter) DmStatementQueryContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (ret *DmRows, err error) {
var logRecord = s.logInfo.logRecord.Reset()
logRecord.Set(s, "queryCtx", convertParams1(args)...)
defer func() {
filter.executeAfter(s.logInfo, logRecord)
filter.doLog(logRecord)
}()
logRecord.SetSql(s.nativeSql, true)
filter.executeBefore(s.logInfo)
ret, err = filterChain.DmStatementQueryContext(s, ctx, args)
if err != nil {
logRecord.SetError(err)
return
}
logRecord.SetReturnValue(ret)
return
}
func (filter *logFilter) DmStatementCheckNamedValue(filterChain *filterChain, s *DmStatement, nv *driver.NamedValue) (err error) {
var logRecord = s.logInfo.logRecord.Reset()
logRecord.Set(s, "checkNamedValue", nv.Value)
defer func() {
filter.doLog(logRecord)
}()
err = filterChain.DmStatementCheckNamedValue(s, nv)
if err != nil {
logRecord.SetError(err)
return
}
return
}
func (filter *logFilter) DmResultLastInsertId(filterChain *filterChain, r *DmResult) (ret int64, err error) {
var logRecord = r.logInfo.logRecord.Reset()
logRecord.Set(r, "lastInsertId")
defer func() {
filter.doLog(logRecord)
}()
ret, err = filterChain.DmResultLastInsertId(r)
if err != nil {
logRecord.SetError(err)
return
}
logRecord.SetReturnValue(ret)
return
}
func (filter *logFilter) DmResultRowsAffected(filterChain *filterChain, r *DmResult) (ret int64, err error) {
var logRecord = r.logInfo.logRecord.Reset()
logRecord.Set(r, "rowsAffected")
defer func() {
filter.doLog(logRecord)
}()
ret, err = filterChain.DmResultRowsAffected(r)
if err != nil {
logRecord.SetError(err)
return
}
logRecord.SetReturnValue(ret)
return
}
func (filter *logFilter) DmRowsColumns(filterChain *filterChain, r *DmRows) (ret []string) {
var logRecord = r.logInfo.logRecord.Reset()
logRecord.Set(r, "columns")
defer func() {
filter.doLog(logRecord)
}()
ret = filterChain.DmRowsColumns(r)
logRecord.SetReturnValue(ret)
return
}
func (filter *logFilter) DmRowsClose(filterChain *filterChain, r *DmRows) (err error) {
var logRecord = r.logInfo.logRecord.Reset()
logRecord.Set(r, "close")
defer func() {
filter.doLog(logRecord)
}()
err = filterChain.DmRowsClose(r)
if err != nil {
logRecord.SetError(err)
return
}
return
}
func (filter *logFilter) DmRowsNext(filterChain *filterChain, r *DmRows, dest []driver.Value) (err error) {
var logRecord = r.logInfo.logRecord.Reset()
logRecord.Set(r, "next", convertParams2(dest)...)
defer func() {
filter.doLog(logRecord)
}()
err = filterChain.DmRowsNext(r, dest)
if err != nil && err != io.EOF {
logRecord.SetError(err)
return
}
return
}
func (filter *logFilter) DmRowsHasNextResultSet(filterChain *filterChain, r *DmRows) (ret bool) {
var logRecord = r.logInfo.logRecord.Reset()
logRecord.Set(r, "hasNextResultSet")
defer func() {
filter.doLog(logRecord)
}()
ret = filterChain.DmRowsHasNextResultSet(r)
logRecord.SetReturnValue(ret)
return
}
func (filter *logFilter) DmRowsNextResultSet(filterChain *filterChain, r *DmRows) (err error) {
var logRecord = r.logInfo.logRecord.Reset()
logRecord.Set(r, "nextResultSet")
defer func() {
filter.doLog(logRecord)
}()
err = filterChain.DmRowsNextResultSet(r)
if err != nil && err != io.EOF {
logRecord.SetError(err)
return
}
return
}
func (filter *logFilter) DmRowsColumnTypeScanType(filterChain *filterChain, r *DmRows, index int) (ret reflect.Type) {
var logRecord = r.logInfo.logRecord.Reset()
logRecord.Set(r, "columnTypeScanType", index)
defer func() {
filter.doLog(logRecord)
}()
ret = filterChain.DmRowsColumnTypeScanType(r, index)
logRecord.SetReturnValue(ret)
return
}
func (filter *logFilter) DmRowsColumnTypeDatabaseTypeName(filterChain *filterChain, r *DmRows, index int) (ret string) {
var logRecord = r.logInfo.logRecord.Reset()
logRecord.Set(r, "columnTypeDatabaseTypeName", index)
defer func() {
filter.doLog(logRecord)
}()
ret = filterChain.DmRowsColumnTypeDatabaseTypeName(r, index)
logRecord.SetReturnValue(ret)
return
}
func (filter *logFilter) DmRowsColumnTypeLength(filterChain *filterChain, r *DmRows, index int) (length int64, ok bool) {
var logRecord = r.logInfo.logRecord.Reset()
logRecord.Set(r, "columnTypeLength", index)
defer func() {
filter.doLog(logRecord)
}()
length, ok = filterChain.DmRowsColumnTypeLength(r, index)
if ok {
logRecord.SetReturnValue(length)
} else {
logRecord.SetReturnValue(-1)
}
return
}
func (filter *logFilter) DmRowsColumnTypeNullable(filterChain *filterChain, r *DmRows, index int) (nullable, ok bool) {
var logRecord = r.logInfo.logRecord.Reset()
logRecord.Set(r, "columnTypeNullable", index)
defer func() {
filter.doLog(logRecord)
}()
nullable, ok = filterChain.DmRowsColumnTypeNullable(r, index)
if ok {
logRecord.SetReturnValue(nullable)
} else {
logRecord.SetReturnValue(false)
}
return
}
func (filter *logFilter) DmRowsColumnTypePrecisionScale(filterChain *filterChain, r *DmRows, index int) (precision, scale int64, ok bool) {
var logRecord = r.logInfo.logRecord.Reset()
logRecord.Set(r, "columnTypePrecisionScale", index)
defer func() {
filter.doLog(logRecord)
}()
precision, scale, ok = filterChain.DmRowsColumnTypePrecisionScale(r, index)
if ok {
logRecord.SetReturnValue(strconv.FormatInt(precision, 10) + "&" + strconv.FormatInt(scale, 10))
} else {
logRecord.SetReturnValue("-1&-1")
}
return
}
func (filter *logFilter) executeBefore(logInfo *logInfo) {
if LogFilterLogger.IsSqlEnabled() {
logInfo.lastExecuteStartNano = time.Now()
}
}
func (filter *logFilter) executeAfter(logInfo *logInfo, record *LogRecord) {
if LogFilterLogger.IsSqlEnabled() {
record.SetUsedTime(time.Since(logInfo.lastExecuteStartNano))
}
}
func (filter *logFilter) doLog(record *LogRecord) {
if record == nil {
return
}
if record.GetError() != nil {
LogFilterLogger.ErrorWithErr(record.ToString(), record.GetError())
} else if record.GetSql() != "" && LogFilterLogger.IsSqlEnabled() {
LogFilterLogger.Sql(record.ToString())
} else {
LogFilterLogger.Info(record.ToString())
}
}
/************************************************************************************************************/
type Logger struct {
}
var LogFilterLogger = &Logger{}
var ConnLogger = &Logger{}
var AccessLogger = &Logger{}
func (logger Logger) IsDebugEnabled() bool {
return LogLevel >= LOG_DEBUG
}
func (logger Logger) IsErrorEnabled() bool {
return LogLevel >= LOG_ERROR
}
func (logger Logger) IsInfoEnabled() bool {
return LogLevel >= LOG_INFO
}
func (logger Logger) IsWarnEnabled() bool {
return LogLevel >= LOG_WARN
}
func (logger Logger) IsSqlEnabled() bool {
return LogLevel >= LOG_SQL
}
func (logger Logger) Debug(msg string) {
if logger.IsDebugEnabled() {
logger.println(logger.formatHead("DEBUG") + msg)
}
}
func (logger Logger) DebugWithErr(msg string, err error) {
if logger.IsDebugEnabled() {
if e, ok := err.(*DmError); ok {
logger.println(logger.formatHead("DEBUG") + msg + util.LINE_SEPARATOR + e.Stack())
} else {
logger.println(logger.formatHead("DEBUG") + msg + util.LINE_SEPARATOR + err.Error())
}
}
}
func (logger Logger) Info(msg string) {
if logger.IsInfoEnabled() {
logger.println(logger.formatHead("INFO ") + msg)
}
}
func (logger Logger) Sql(msg string) {
if logger.IsSqlEnabled() {
logger.println(logger.formatHead("SQL ") + msg)
}
}
func (logger Logger) Warn(msg string) {
if logger.IsWarnEnabled() {
logger.println(logger.formatHead("WARN ") + msg)
}
}
func (logger Logger) ErrorWithErr(msg string, err error) {
//if e, ok := err.(*DmError); ok {
// logger.println(logger.formatHead("ERROR") + msg + util.LINE_SEPARATOR + e.Stack())
//} else {
logger.println(logger.formatHead("ERROR") + msg + util.LINE_SEPARATOR + err.Error())
//}
}
// TODO: 获取goroutine objId
func (logger Logger) formatHead(head string) string {
// return "[" + head + " - " + StringUtil.formatTime() + "] tid:" + Thread.currentThread().getId();
return "[" + head + " - " + util.StringUtil.FormatTime() + "]"
}
func (logger Logger) println(msg string) {
goMap["log"].(*logWriter).WriteLine(msg)
}
/*************************************************************************************************/
func formatSource(source interface{}) string {
if source == nil {
return ""
}
var str string
switch src := source.(type) {
case string:
str += src
case *DmDriver:
str += formatDriver(src)
case *DmConnector:
str += formatContor(src)
case *DmConnection:
str += formatConn(src)
case *DmStatement:
str += formatConn(src.dmConn) + ", "
str += formatStmt(src)
case *DmResult:
str += formatConn(src.dmStmt.dmConn) + ", "
str += formatStmt(src.dmStmt) + ", "
str += formatRs(src)
case *DmRows:
str += formatConn(src.CurrentRows.dmStmt.dmConn) + ", "
str += formatStmt(src.CurrentRows.dmStmt) + ", "
str += formatRows(src)
default:
str += reflect.TypeOf(src).String() + "@" + reflect.ValueOf(src).Addr().String()
}
return str
}
func formatDriver(driver *DmDriver) string {
if driver != nil && driver.logInfo != nil {
return "driver-" + strconv.FormatInt(driver.getID(), 10)
}
return "driver-nil"
}
func formatContor(contor *DmConnector) string {
if contor != nil && contor.logInfo != nil {
return "contor-" + strconv.FormatInt(contor.getID(), 10)
}
return "contor-nil"
}
func formatConn(conn *DmConnection) string {
if conn != nil && conn.logInfo != nil {
return "conn-0x" + strconv.FormatInt(conn.SessionID, 16)
}
return "conn-nil"
}
func formatStmt(stmt *DmStatement) string {
if stmt != nil && stmt.logInfo != nil {
return "stmt-" + strconv.Itoa(int(stmt.id))
}
return "stmt-nil"
}
func formatRs(result *DmResult) string {
if result != nil && result.logInfo != nil {
return "rs-" + strconv.FormatInt(result.getID(), 10)
}
return "rs-nil"
}
func formatRows(rows *DmRows) string {
if rows != nil && rows.logInfo != nil {
return "rows-" + strconv.FormatInt(rows.getID(), 10)
}
return "rows-nil"
}
func formatTrace(source string, sql string, method string, returnValue interface{}, params ...interface{}) string {
var str string
if source != "" {
str += "{ " + source + " } "
}
str += method + "("
var paramStartIndex = 0
if params != nil && len(params) > paramStartIndex {
for i := paramStartIndex; i < len(params); i++ {
if i != paramStartIndex {
str += ", "
}
if params[i] != nil {
str += reflect.TypeOf(params[i]).String()
} else {
str += "nil"
}
}
}
str += ")"
if returnValue != nil {
str += ": " + formatReturn(returnValue)
}
str += "; "
if params != nil && len(params) > paramStartIndex {
str += "[PARAMS]: "
for i := paramStartIndex; i < len(params); i++ {
if i != 0 {
str += ", "
}
//if s, ok := params[i].(driver.NamedValue); ok {
// str += fmt.Sprintf("%v", s.Value)
//} else {
str += fmt.Sprintf("%v", params[i])
//}
}
str += "; "
}
if sql != "" {
str += "[SQL]: " + sql + "; "
}
return str
}
func formatReturn(returnObj interface{}) string {
var str string
switch o := returnObj.(type) {
case *DmConnection:
str = formatConn(o)
case *DmStatement:
str = formatStmt(o)
case *DmResult:
str = formatRs(o)
case *DmRows:
str = formatRows(o)
case string:
str = `"` + o + `"`
case nullData:
str = "nil"
default:
str = "unknown"
}
return str
}
func formatUsedTime(duration time.Duration) string {
return "[USED TIME]: " + duration.String()
}
/************************************************************************************************************/
type nullData struct{}
var null = nullData{}
type LogRecord struct {
source string
method string
params []interface{}
returnValue interface{}
e error
usedTime time.Duration
sql string
logSql bool // 是否需要记录sql(exec,query等需要在日志中记录sql语句)
}
func (record *LogRecord) Reset() *LogRecord {
record.source = ""
record.method = ""
record.params = nil
record.returnValue = nil
record.e = nil
record.usedTime = 0
record.sql = ""
record.logSql = false
return record
}
func (record *LogRecord) Set(source interface{}, method string, params ...interface{}) {
record.source = formatSource(source)
record.method = method
record.params = params
}
func (record *LogRecord) SetReturnValue(retValue interface{}) {
if retValue == nil {
record.returnValue = null
} else {
record.returnValue = retValue
}
}
func (record *LogRecord) GetReturnValue() interface{} {
return record.returnValue
}
func (record *LogRecord) SetSql(sql string, logSql bool) {
record.sql = sql
record.logSql = logSql
}
func (record *LogRecord) GetSql() string {
return record.sql
}
func (record *LogRecord) SetUsedTime(usedTime time.Duration) {
record.usedTime = usedTime
}
func (record *LogRecord) GetUsedTime() time.Duration {
return record.usedTime
}
func (record *LogRecord) SetError(err error) {
record.e = err
}
func (record *LogRecord) GetError() error {
return record.e
}
func (record *LogRecord) ToString() string {
var sql string
if record.logSql && record.sql != "" {
sql = record.sql
}
var str string
str += formatTrace(record.source, sql, record.method, record.returnValue, record.params...)
if record.usedTime > 0 {
str += formatUsedTime(record.usedTime)
}
return str
}
func convertParams1(args []driver.NamedValue) []interface{} {
tmp := make([]interface{}, len(args))
for i := 0; i < len(tmp); i++ {
tmp[i] = args[i].Value
}
return tmp
}
func convertParams2(args []driver.Value) []interface{} {
tmp := make([]interface{}, len(args))
for i := 0; i < len(tmp); i++ {
tmp[i] = args[i]
}
return tmp
}
+516
View File
@@ -0,0 +1,516 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"context"
"database/sql/driver"
"io"
"reflect"
"time"
"gitee.com/chunanyong/dm/util"
)
const SQL_GET_DSC_EP_SITE = "SELECT " +
"dsc.ep_seqno, " +
"(CASE mal.MAL_INST_HOST WHEN '' THEN mal.MAL_HOST ELSE mal.MAL_INST_HOST END) as ep_host, " +
"dcr.EP_PORT, " +
"dsc.EP_STATUS " +
"FROM V$DSC_EP_INFO dsc " +
"LEFT join V$DM_MAL_INI mal " +
"on dsc.EP_NAME = mal.MAL_INST_NAME " +
"LEFT join (SELECT grp.GROUP_TYPE GROUP_TYPE, ep.* FROM SYS.\"V$DCR_GROUP\" grp, SYS.\"V$DCR_EP\" ep where grp.GROUP_NAME = ep.GROUP_NAME) dcr " +
"on dsc.EP_NAME = dcr.EP_NAME and GROUP_TYPE = 'DB' order by dsc.ep_seqno asc;"
type reconnectFilter struct {
}
// 一定抛错
func (rf *reconnectFilter) autoReconnect(connection *DmConnection, err error) error {
if dmErr, ok := err.(*DmError); ok {
if dmErr.ErrCode == ECGO_COMMUNITION_ERROR.ErrCode || dmErr.ErrCode == ECGO_CONNECTION_CLOSED.ErrCode {
if connection.dmConnector.driverReconnect {
return rf.reconnect(connection, dmErr.getErrText())
} else {
connection.Access.Close()
connection.closed.Set(true)
return driver.ErrBadConn
}
}
}
return err
}
// 一定抛错
func (rf *reconnectFilter) reconnect(connection *DmConnection, reason string) error {
// 读写分离,重连需要处理备机
var err error
if connection.dmConnector.rwSeparate > RW_SEPARATE_OFF {
err = RWUtil.reconnect(connection)
} else {
err = connection.reconnect()
}
if err != nil {
connection.closed.Set(true)
return ECGO_CONNECTION_SWITCH_FAILED.addDetailln(reason).throw()
}
// 重连成功
connection.closed.Set(false)
return ECGO_CONNECTION_SWITCHED.addDetailln(reason).throw()
}
func (rf *reconnectFilter) loadDscEpSites(conn *DmConnection) []*ep {
stmt, rs, err := conn.driverQuery(SQL_GET_DSC_EP_SITE)
if err != nil {
return nil
}
defer func() {
rs.close()
stmt.close()
}()
epList := make([]*ep, 0)
dest := make([]driver.Value, 4)
for err = rs.next(dest); err != io.EOF; err = rs.next(dest) {
ep := newEP(dest[1].(string), dest[2].(int32))
ep.epSeqno = dest[0].(int32)
if util.StringUtil.EqualsIgnoreCase(dest[3].(string), "OK") {
ep.epStatus = EP_STATUS_OK
} else {
ep.epStatus = EP_STATUS_ERROR
}
epList = append(epList, ep)
}
return epList
}
func (rf *reconnectFilter) checkAndRecover(conn *DmConnection) error {
if conn.dmConnector.doSwitch != DO_SWITCH_WHEN_EP_RECOVER {
return nil
}
// check trx finish
if !conn.trxFinish {
return nil
}
var curIndex = conn.getIndexOnEPGroup()
if curIndex == 0 || (time.Now().UnixNano()/1000000-conn.recoverInfo.checkEpRecoverTs) < int64(conn.dmConnector.switchInterval) {
return nil
}
// check db recover
var dscEps []*ep
if conn.dmConnector.cluster == CLUSTER_TYPE_DSC {
dscEps = rf.loadDscEpSites(conn)
}
if dscEps == nil || len(dscEps) == 0 {
return nil
}
var recover = false
for _, okEp := range dscEps {
if okEp.epStatus != EP_STATUS_OK {
continue
}
for i := int32(0); i < curIndex; i++ {
ep := conn.dmConnector.group.epList[i]
if okEp.host == ep.host && okEp.port == ep.port {
recover = true
break
}
}
if recover {
break
}
}
conn.recoverInfo.checkEpRecoverTs = time.Now().UnixNano() / 1000000
if !recover {
return nil
}
if conn.dmConnector.driverReconnect {
return conn.reconnect()
} else {
conn.Access.Close()
conn.closed.Set(false)
return ECGO_CONNECTION_CLOSED.throw()
}
//return driver.ErrBadConn
// do reconnect
//return conn.reconnect()
}
// DmDriver
func (rf *reconnectFilter) DmDriverOpen(filterChain *filterChain, d *DmDriver, dsn string) (*DmConnection, error) {
return filterChain.DmDriverOpen(d, dsn)
}
func (rf *reconnectFilter) DmDriverOpenConnector(filterChain *filterChain, d *DmDriver, dsn string) (*DmConnector, error) {
return filterChain.DmDriverOpenConnector(d, dsn)
}
// DmConnector
func (rf *reconnectFilter) DmConnectorConnect(filterChain *filterChain, c *DmConnector, ctx context.Context) (*DmConnection, error) {
return filterChain.DmConnectorConnect(c, ctx)
}
func (rf *reconnectFilter) DmConnectorDriver(filterChain *filterChain, c *DmConnector) *DmDriver {
return filterChain.DmConnectorDriver(c)
}
// DmConnection
func (rf *reconnectFilter) DmConnectionBegin(filterChain *filterChain, c *DmConnection) (*DmConnection, error) {
dc, err := filterChain.DmConnectionBegin(c)
if err != nil {
return nil, rf.autoReconnect(c, err)
}
return dc, err
}
func (rf *reconnectFilter) DmConnectionBeginTx(filterChain *filterChain, c *DmConnection, ctx context.Context, opts driver.TxOptions) (*DmConnection, error) {
dc, err := filterChain.DmConnectionBeginTx(c, ctx, opts)
if err != nil {
return nil, rf.autoReconnect(c, err)
}
return dc, err
}
func (rf *reconnectFilter) DmConnectionCommit(filterChain *filterChain, c *DmConnection) error {
if err := filterChain.DmConnectionCommit(c); err != nil {
return rf.autoReconnect(c, err)
}
if err := rf.checkAndRecover(c); err != nil {
return rf.autoReconnect(c, err)
}
return nil
}
func (rf *reconnectFilter) DmConnectionRollback(filterChain *filterChain, c *DmConnection) error {
err := filterChain.DmConnectionRollback(c)
if err != nil {
err = rf.autoReconnect(c, err)
}
return err
}
func (rf *reconnectFilter) DmConnectionClose(filterChain *filterChain, c *DmConnection) error {
err := filterChain.DmConnectionClose(c)
if err != nil {
err = rf.autoReconnect(c, err)
}
return err
}
func (rf *reconnectFilter) DmConnectionPing(filterChain *filterChain, c *DmConnection, ctx context.Context) error {
err := filterChain.DmConnectionPing(c, ctx)
if err != nil {
err = rf.autoReconnect(c, err)
}
return err
}
func (rf *reconnectFilter) DmConnectionExec(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (*DmResult, error) {
if err := rf.checkAndRecover(c); err != nil {
return nil, rf.autoReconnect(c, err)
}
dr, err := filterChain.DmConnectionExec(c, query, args)
if err != nil {
return nil, rf.autoReconnect(c, err)
}
return dr, err
}
func (rf *reconnectFilter) DmConnectionExecContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmResult, error) {
if err := rf.checkAndRecover(c); err != nil {
return nil, rf.autoReconnect(c, err)
}
dr, err := filterChain.DmConnectionExecContext(c, ctx, query, args)
if err != nil {
return nil, rf.autoReconnect(c, err)
}
return dr, err
}
func (rf *reconnectFilter) DmConnectionQuery(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (*DmRows, error) {
if err := rf.checkAndRecover(c); err != nil {
return nil, rf.autoReconnect(c, err)
}
dr, err := filterChain.DmConnectionQuery(c, query, args)
if err != nil {
return nil, rf.autoReconnect(c, err)
}
return dr, err
}
func (rf *reconnectFilter) DmConnectionQueryContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmRows, error) {
if err := rf.checkAndRecover(c); err != nil {
return nil, rf.autoReconnect(c, err)
}
dr, err := filterChain.DmConnectionQueryContext(c, ctx, query, args)
if err != nil {
return nil, rf.autoReconnect(c, err)
}
return dr, err
}
func (rf *reconnectFilter) DmConnectionPrepare(filterChain *filterChain, c *DmConnection, query string) (*DmStatement, error) {
ds, err := filterChain.DmConnectionPrepare(c, query)
if err != nil {
return nil, rf.autoReconnect(c, err)
}
return ds, err
}
func (rf *reconnectFilter) DmConnectionPrepareContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string) (*DmStatement, error) {
ds, err := filterChain.DmConnectionPrepareContext(c, ctx, query)
if err != nil {
return nil, rf.autoReconnect(c, err)
}
return ds, err
}
func (rf *reconnectFilter) DmConnectionResetSession(filterChain *filterChain, c *DmConnection, ctx context.Context) error {
err := filterChain.DmConnectionResetSession(c, ctx)
if err != nil {
err = rf.autoReconnect(c, err)
}
return err
}
func (rf *reconnectFilter) DmConnectionCheckNamedValue(filterChain *filterChain, c *DmConnection, nv *driver.NamedValue) error {
err := filterChain.DmConnectionCheckNamedValue(c, nv)
if err != nil {
err = rf.autoReconnect(c, err)
}
return err
}
// DmStatement
func (rf *reconnectFilter) DmStatementClose(filterChain *filterChain, s *DmStatement) error {
err := filterChain.DmStatementClose(s)
if err != nil {
err = rf.autoReconnect(s.dmConn, err)
}
return err
}
func (rf *reconnectFilter) DmStatementNumInput(filterChain *filterChain, s *DmStatement) int {
var ret int
defer func() {
err := recover()
if err != nil {
rf.autoReconnect(s.dmConn, err.(error))
ret = 0
}
}()
ret = filterChain.DmStatementNumInput(s)
return ret
}
func (rf *reconnectFilter) DmStatementExec(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmResult, error) {
if err := rf.checkAndRecover(s.dmConn); err != nil {
return nil, rf.autoReconnect(s.dmConn, err)
}
dr, err := filterChain.DmStatementExec(s, args)
if err != nil {
return nil, rf.autoReconnect(s.dmConn, err)
}
return dr, err
}
func (rf *reconnectFilter) DmStatementExecContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmResult, error) {
if err := rf.checkAndRecover(s.dmConn); err != nil {
return nil, rf.autoReconnect(s.dmConn, err)
}
dr, err := filterChain.DmStatementExecContext(s, ctx, args)
if err != nil {
return nil, rf.autoReconnect(s.dmConn, err)
}
return dr, err
}
func (rf *reconnectFilter) DmStatementQuery(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmRows, error) {
if err := rf.checkAndRecover(s.dmConn); err != nil {
return nil, rf.autoReconnect(s.dmConn, err)
}
dr, err := filterChain.DmStatementQuery(s, args)
if err != nil {
return nil, rf.autoReconnect(s.dmConn, err)
}
return dr, err
}
func (rf *reconnectFilter) DmStatementQueryContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmRows, error) {
if err := rf.checkAndRecover(s.dmConn); err != nil {
return nil, rf.autoReconnect(s.dmConn, err)
}
dr, err := filterChain.DmStatementQueryContext(s, ctx, args)
if err != nil {
return nil, rf.autoReconnect(s.dmConn, err)
}
return dr, err
}
func (rf *reconnectFilter) DmStatementCheckNamedValue(filterChain *filterChain, s *DmStatement, nv *driver.NamedValue) error {
err := filterChain.DmStatementCheckNamedValue(s, nv)
if err != nil {
err = rf.autoReconnect(s.dmConn, err)
}
return err
}
// DmResult
func (rf *reconnectFilter) DmResultLastInsertId(filterChain *filterChain, r *DmResult) (int64, error) {
i, err := filterChain.DmResultLastInsertId(r)
if err != nil {
err = rf.autoReconnect(r.dmStmt.dmConn, err)
return 0, err
}
return i, err
}
func (rf *reconnectFilter) DmResultRowsAffected(filterChain *filterChain, r *DmResult) (int64, error) {
i, err := filterChain.DmResultRowsAffected(r)
if err != nil {
err = rf.autoReconnect(r.dmStmt.dmConn, err)
return 0, err
}
return i, err
}
// DmRows
func (rf *reconnectFilter) DmRowsColumns(filterChain *filterChain, r *DmRows) []string {
var ret []string
defer func() {
err := recover()
if err != nil {
rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err.(error))
ret = nil
}
}()
ret = filterChain.DmRowsColumns(r)
return ret
}
func (rf *reconnectFilter) DmRowsClose(filterChain *filterChain, r *DmRows) error {
err := filterChain.DmRowsClose(r)
if err != nil {
err = rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err)
}
return err
}
func (rf *reconnectFilter) DmRowsNext(filterChain *filterChain, r *DmRows, dest []driver.Value) error {
err := filterChain.DmRowsNext(r, dest)
if err != nil {
err = rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err)
}
return err
}
func (rf *reconnectFilter) DmRowsHasNextResultSet(filterChain *filterChain, r *DmRows) bool {
var ret bool
defer func() {
err := recover()
if err != nil {
rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err.(error))
ret = false
}
}()
ret = filterChain.DmRowsHasNextResultSet(r)
return ret
}
func (rf *reconnectFilter) DmRowsNextResultSet(filterChain *filterChain, r *DmRows) error {
err := filterChain.DmRowsNextResultSet(r)
if err != nil {
err = rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err)
}
return err
}
func (rf *reconnectFilter) DmRowsColumnTypeScanType(filterChain *filterChain, r *DmRows, index int) reflect.Type {
var ret reflect.Type
defer func() {
err := recover()
if err != nil {
rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err.(error))
ret = scanTypeUnknown
}
}()
ret = filterChain.DmRowsColumnTypeScanType(r, index)
return ret
}
func (rf *reconnectFilter) DmRowsColumnTypeDatabaseTypeName(filterChain *filterChain, r *DmRows, index int) string {
var ret string
defer func() {
err := recover()
if err != nil {
rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err.(error))
ret = ""
}
}()
ret = filterChain.DmRowsColumnTypeDatabaseTypeName(r, index)
return ret
}
func (rf *reconnectFilter) DmRowsColumnTypeLength(filterChain *filterChain, r *DmRows, index int) (length int64, ok bool) {
defer func() {
err := recover()
if err != nil {
rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err.(error))
length, ok = 0, false
}
}()
return filterChain.DmRowsColumnTypeLength(r, index)
}
func (rf *reconnectFilter) DmRowsColumnTypeNullable(filterChain *filterChain, r *DmRows, index int) (nullable, ok bool) {
defer func() {
err := recover()
if err != nil {
rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err.(error))
nullable, ok = false, false
}
}()
return filterChain.DmRowsColumnTypeNullable(r, index)
}
func (rf *reconnectFilter) DmRowsColumnTypePrecisionScale(filterChain *filterChain, r *DmRows, index int) (precision, scale int64, ok bool) {
defer func() {
err := recover()
if err != nil {
rf.autoReconnect(r.CurrentRows.dmStmt.dmConn, err.(error))
precision, scale, ok = 0, 0, false
}
}()
return filterChain.DmRowsColumnTypePrecisionScale(r, index)
}
+310
View File
@@ -0,0 +1,310 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"context"
"database/sql/driver"
"reflect"
)
type rwFilter struct {
}
//DmDriver
func (rwf *rwFilter) DmDriverOpen(filterChain *filterChain, d *DmDriver, dsn string) (*DmConnection, error) {
return filterChain.DmDriverOpen(d, dsn)
}
func (rwf *rwFilter) DmDriverOpenConnector(filterChain *filterChain, d *DmDriver, dsn string) (*DmConnector, error) {
return filterChain.DmDriverOpenConnector(d, dsn)
}
//DmConnector
func (rwf *rwFilter) DmConnectorConnect(filterChain *filterChain, c *DmConnector, ctx context.Context) (*DmConnection, error) {
return RWUtil.connect(c, ctx)
}
func (rwf *rwFilter) DmConnectorDriver(filterChain *filterChain, c *DmConnector) *DmDriver {
return filterChain.DmConnectorDriver(c)
}
//DmConnection
func (rwf *rwFilter) DmConnectionBegin(filterChain *filterChain, c *DmConnection) (*DmConnection, error) {
if RWUtil.isStandbyAlive(c) {
_, err := c.rwInfo.connStandby.begin()
if err != nil {
RWUtil.afterExceptionOnStandby(c, err)
}
}
return filterChain.DmConnectionBegin(c)
}
func (rwf *rwFilter) DmConnectionBeginTx(filterChain *filterChain, c *DmConnection, ctx context.Context, opts driver.TxOptions) (*DmConnection, error) {
if RWUtil.isStandbyAlive(c) {
_, err := c.rwInfo.connStandby.beginTx(ctx, opts)
if err != nil {
RWUtil.afterExceptionOnStandby(c, err)
}
}
return filterChain.DmConnectionBeginTx(c, ctx, opts)
}
func (rwf *rwFilter) DmConnectionCommit(filterChain *filterChain, c *DmConnection) error {
if RWUtil.isStandbyAlive(c) {
err := c.rwInfo.connStandby.commit()
if err != nil {
RWUtil.afterExceptionOnStandby(c, err)
}
}
return filterChain.DmConnectionCommit(c)
}
func (rwf *rwFilter) DmConnectionRollback(filterChain *filterChain, c *DmConnection) error {
if RWUtil.isStandbyAlive(c) {
err := c.rwInfo.connStandby.rollback()
if err != nil {
RWUtil.afterExceptionOnStandby(c, err)
}
}
return filterChain.DmConnectionRollback(c)
}
func (rwf *rwFilter) DmConnectionClose(filterChain *filterChain, c *DmConnection) error {
if RWUtil.isStandbyAlive(c) {
err := c.rwInfo.connStandby.close()
if err != nil {
RWUtil.afterExceptionOnStandby(c, err)
}
}
return filterChain.DmConnectionClose(c)
}
func (rwf *rwFilter) DmConnectionPing(filterChain *filterChain, c *DmConnection, ctx context.Context) error {
return filterChain.DmConnectionPing(c, ctx)
}
func (rwf *rwFilter) DmConnectionExec(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (*DmResult, error) {
ret, err := RWUtil.executeByConn(c, query, func() (interface{}, error) {
return c.rwInfo.connCurrent.exec(query, args)
}, func(otherConn *DmConnection) (interface{}, error) {
return otherConn.exec(query, args)
})
if err != nil {
return nil, err
}
return ret.(*DmResult), nil
}
func (rwf *rwFilter) DmConnectionExecContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmResult, error) {
ret, err := RWUtil.executeByConn(c, query, func() (interface{}, error) {
return c.rwInfo.connCurrent.execContext(ctx, query, args)
}, func(otherConn *DmConnection) (interface{}, error) {
return otherConn.execContext(ctx, query, args)
})
if err != nil {
return nil, err
}
return ret.(*DmResult), nil
}
func (rwf *rwFilter) DmConnectionQuery(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (*DmRows, error) {
ret, err := RWUtil.executeByConn(c, query, func() (interface{}, error) {
return c.rwInfo.connCurrent.query(query, args)
}, func(otherConn *DmConnection) (interface{}, error) {
return otherConn.query(query, args)
})
if err != nil {
return nil, err
}
return ret.(*DmRows), nil
}
func (rwf *rwFilter) DmConnectionQueryContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmRows, error) {
ret, err := RWUtil.executeByConn(c, query, func() (interface{}, error) {
return c.rwInfo.connCurrent.queryContext(ctx, query, args)
}, func(otherConn *DmConnection) (interface{}, error) {
return otherConn.queryContext(ctx, query, args)
})
if err != nil {
return nil, err
}
return ret.(*DmRows), nil
}
func (rwf *rwFilter) DmConnectionPrepare(filterChain *filterChain, c *DmConnection, query string) (*DmStatement, error) {
stmt, err := c.prepare(query)
if err != nil {
return nil, err
}
stmt.rwInfo.stmtCurrent = stmt
stmt.rwInfo.readOnly = RWUtil.checkReadonlyByStmt(stmt)
if RWUtil.isCreateStandbyStmt(stmt) {
stmt.rwInfo.stmtStandby, err = c.rwInfo.connStandby.prepare(query)
if err == nil {
stmt.rwInfo.stmtCurrent = stmt.rwInfo.stmtStandby
} else {
RWUtil.afterExceptionOnStandby(c, err)
}
}
return stmt, nil
}
func (rwf *rwFilter) DmConnectionPrepareContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string) (*DmStatement, error) {
stmt, err := c.prepareContext(ctx, query)
if err != nil {
return nil, err
}
stmt.rwInfo.stmtCurrent = stmt
stmt.rwInfo.readOnly = RWUtil.checkReadonlyByStmt(stmt)
if RWUtil.isCreateStandbyStmt(stmt) {
stmt.rwInfo.stmtStandby, err = c.rwInfo.connStandby.prepareContext(ctx, query)
if err == nil {
stmt.rwInfo.stmtCurrent = stmt.rwInfo.stmtStandby
} else {
RWUtil.afterExceptionOnStandby(c, err)
}
}
return stmt, nil
}
func (rwf *rwFilter) DmConnectionResetSession(filterChain *filterChain, c *DmConnection, ctx context.Context) error {
if RWUtil.isStandbyAlive(c) {
err := c.rwInfo.connStandby.resetSession(ctx)
if err != nil {
RWUtil.afterExceptionOnStandby(c, err)
}
}
return filterChain.DmConnectionResetSession(c, ctx)
}
func (rwf *rwFilter) DmConnectionCheckNamedValue(filterChain *filterChain, c *DmConnection, nv *driver.NamedValue) error {
return filterChain.DmConnectionCheckNamedValue(c, nv)
}
//DmStatement
func (rwf *rwFilter) DmStatementClose(filterChain *filterChain, s *DmStatement) error {
if RWUtil.isStandbyStatementValid(s) {
err := s.rwInfo.stmtStandby.close()
if err != nil {
RWUtil.afterExceptionOnStandby(s.dmConn, err)
}
}
return filterChain.DmStatementClose(s)
}
func (rwf *rwFilter) DmStatementNumInput(filterChain *filterChain, s *DmStatement) int {
return filterChain.DmStatementNumInput(s)
}
func (rwf *rwFilter) DmStatementExec(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmResult, error) {
ret, err := RWUtil.executeByStmt(s, func() (interface{}, error) {
return s.rwInfo.stmtCurrent.exec(args)
}, func(otherStmt *DmStatement) (interface{}, error) {
return otherStmt.exec(args)
})
if err != nil {
return nil, err
}
return ret.(*DmResult), nil
}
func (rwf *rwFilter) DmStatementExecContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmResult, error) {
ret, err := RWUtil.executeByStmt(s, func() (interface{}, error) {
return s.rwInfo.stmtCurrent.execContext(ctx, args)
}, func(otherStmt *DmStatement) (interface{}, error) {
return otherStmt.execContext(ctx, args)
})
if err != nil {
return nil, err
}
return ret.(*DmResult), nil
}
func (rwf *rwFilter) DmStatementQuery(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmRows, error) {
ret, err := RWUtil.executeByStmt(s, func() (interface{}, error) {
return s.rwInfo.stmtCurrent.query(args)
}, func(otherStmt *DmStatement) (interface{}, error) {
return otherStmt.query(args)
})
if err != nil {
return nil, err
}
return ret.(*DmRows), nil
}
func (rwf *rwFilter) DmStatementQueryContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmRows, error) {
ret, err := RWUtil.executeByStmt(s, func() (interface{}, error) {
return s.rwInfo.stmtCurrent.queryContext(ctx, args)
}, func(otherStmt *DmStatement) (interface{}, error) {
return otherStmt.queryContext(ctx, args)
})
if err != nil {
return nil, err
}
return ret.(*DmRows), nil
}
func (rwf *rwFilter) DmStatementCheckNamedValue(filterChain *filterChain, s *DmStatement, nv *driver.NamedValue) error {
return filterChain.DmStatementCheckNamedValue(s, nv)
}
//DmResult
func (rwf *rwFilter) DmResultLastInsertId(filterChain *filterChain, r *DmResult) (int64, error) {
return filterChain.DmResultLastInsertId(r)
}
func (rwf *rwFilter) DmResultRowsAffected(filterChain *filterChain, r *DmResult) (int64, error) {
return filterChain.DmResultRowsAffected(r)
}
//DmRows
func (rwf *rwFilter) DmRowsColumns(filterChain *filterChain, r *DmRows) []string {
return filterChain.DmRowsColumns(r)
}
func (rwf *rwFilter) DmRowsClose(filterChain *filterChain, r *DmRows) error {
return filterChain.DmRowsClose(r)
}
func (rwf *rwFilter) DmRowsNext(filterChain *filterChain, r *DmRows, dest []driver.Value) error {
return filterChain.DmRowsNext(r, dest)
}
func (rwf *rwFilter) DmRowsHasNextResultSet(filterChain *filterChain, r *DmRows) bool {
return filterChain.DmRowsHasNextResultSet(r)
}
func (rwf *rwFilter) DmRowsNextResultSet(filterChain *filterChain, r *DmRows) error {
return filterChain.DmRowsNextResultSet(r)
}
func (rwf *rwFilter) DmRowsColumnTypeScanType(filterChain *filterChain, r *DmRows, index int) reflect.Type {
return filterChain.DmRowsColumnTypeScanType(r, index)
}
func (rwf *rwFilter) DmRowsColumnTypeDatabaseTypeName(filterChain *filterChain, r *DmRows, index int) string {
return filterChain.DmRowsColumnTypeDatabaseTypeName(r, index)
}
func (rwf *rwFilter) DmRowsColumnTypeLength(filterChain *filterChain, r *DmRows, index int) (length int64, ok bool) {
return filterChain.DmRowsColumnTypeLength(r, index)
}
func (rwf *rwFilter) DmRowsColumnTypeNullable(filterChain *filterChain, r *DmRows, index int) (nullable, ok bool) {
return filterChain.DmRowsColumnTypeNullable(r, index)
}
func (rwf *rwFilter) DmRowsColumnTypePrecisionScale(filterChain *filterChain, r *DmRows, index int) (precision, scale int64, ok bool) {
return filterChain.DmRowsColumnTypePrecisionScale(r, index)
}
+607
View File
@@ -0,0 +1,607 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"bytes"
"context"
"database/sql/driver"
"fmt"
"reflect"
"time"
)
type statFilter struct {
}
//DmDriver
func (sf *statFilter) DmDriverOpen(filterChain *filterChain, d *DmDriver, dsn string) (*DmConnection, error) {
conn, err := filterChain.DmDriverOpen(d, dsn)
if err != nil {
return nil, err
}
conn.statInfo.init(conn)
conn.statInfo.setConstructNano()
conn.statInfo.getConnStat().incrementConn()
return conn, nil
}
func (sf *statFilter) DmDriverOpenConnector(filterChain *filterChain, d *DmDriver, dsn string) (*DmConnector, error) {
return filterChain.DmDriverOpenConnector(d, dsn)
}
//DmConnector
func (sf *statFilter) DmConnectorConnect(filterChain *filterChain, c *DmConnector, ctx context.Context) (*DmConnection, error) {
conn, err := filterChain.DmConnectorConnect(c, ctx)
if err != nil {
return nil, err
}
conn.statInfo.init(conn)
conn.statInfo.setConstructNano()
conn.statInfo.getConnStat().incrementConn()
return conn, nil
}
func (sf *statFilter) DmConnectorDriver(filterChain *filterChain, c *DmConnector) *DmDriver {
return filterChain.DmConnectorDriver(c)
}
//DmConnection
func (sf *statFilter) DmConnectionBegin(filterChain *filterChain, c *DmConnection) (*DmConnection, error) {
return filterChain.DmConnectionBegin(c)
}
func (sf *statFilter) DmConnectionBeginTx(filterChain *filterChain, c *DmConnection, ctx context.Context, opts driver.TxOptions) (*DmConnection, error) {
return filterChain.DmConnectionBeginTx(c, ctx, opts)
}
func (sf *statFilter) DmConnectionCommit(filterChain *filterChain, c *DmConnection) error {
err := filterChain.DmConnectionCommit(c)
if err != nil {
return err
}
c.statInfo.getConnStat().incrementCommitCount()
return nil
}
func (sf *statFilter) DmConnectionRollback(filterChain *filterChain, c *DmConnection) error {
err := filterChain.DmConnectionRollback(c)
if err != nil {
return err
}
c.statInfo.getConnStat().incrementRollbackCount()
return nil
}
func (sf *statFilter) DmConnectionClose(filterChain *filterChain, c *DmConnection) error {
if !c.closed.IsSet() {
c.statInfo.getConnStat().decrementStmtByActiveStmtCount(int64(getActiveStmtCount(c)))
c.statInfo.getConnStat().decrementConn()
}
return filterChain.DmConnectionClose(c)
}
func (sf *statFilter) DmConnectionPing(filterChain *filterChain, c *DmConnection, ctx context.Context) error {
return c.ping(ctx)
}
func (sf *statFilter) DmConnectionExec(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (*DmResult, error) {
connExecBefore(c, query)
dr, err := filterChain.DmConnectionExec(c, query, args)
if err != nil {
connExecuteErrorAfter(c, args, err)
return nil, err
}
connExecAfter(c, query, args, int(dr.affectedRows))
return dr, nil
}
func (sf *statFilter) DmConnectionExecContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmResult, error) {
connExecBefore(c, query)
dr, err := filterChain.DmConnectionExecContext(c, ctx, query, args)
if err != nil {
connExecuteErrorAfter(c, args, err)
return nil, err
}
connExecAfter(c, query, args, int(dr.affectedRows))
return dr, nil
}
func (sf *statFilter) DmConnectionQuery(filterChain *filterChain, c *DmConnection, query string, args []driver.Value) (*DmRows, error) {
connQueryBefore(c, query)
dr, err := filterChain.DmConnectionQuery(c, query, args)
if err != nil {
connExecuteErrorAfter(c, args, err)
return nil, err
}
connQueryAfter(c, query, args, dr)
return dr, nil
}
func (sf *statFilter) DmConnectionQueryContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string, args []driver.NamedValue) (*DmRows, error) {
connQueryBefore(c, query)
dr, err := filterChain.DmConnectionQueryContext(c, ctx, query, args)
if err != nil {
connExecuteErrorAfter(c, args, err)
return nil, err
}
connQueryAfter(c, query, args, dr)
return dr, nil
}
func (sf *statFilter) DmConnectionPrepare(filterChain *filterChain, c *DmConnection, query string) (*DmStatement, error) {
stmt, err := filterChain.DmConnectionPrepare(c, query)
if err != nil {
return nil, err
}
statementCreateAfter(c, stmt)
return stmt, nil
}
func (sf *statFilter) DmConnectionPrepareContext(filterChain *filterChain, c *DmConnection, ctx context.Context, query string) (*DmStatement, error) {
stmt, err := filterChain.DmConnectionPrepareContext(c, ctx, query)
if err != nil {
return nil, err
}
statementCreateAfter(c, stmt)
return stmt, nil
}
func (sf *statFilter) DmConnectionResetSession(filterChain *filterChain, c *DmConnection, ctx context.Context) error {
return filterChain.DmConnectionResetSession(c, ctx)
}
func (sf *statFilter) DmConnectionCheckNamedValue(filterChain *filterChain, c *DmConnection, nv *driver.NamedValue) error {
return filterChain.DmConnectionCheckNamedValue(c, nv)
}
//DmStatement
func (sf *statFilter) DmStatementClose(filterChain *filterChain, s *DmStatement) error {
if !s.closed {
statementCloseBefore(s)
}
return filterChain.DmStatementClose(s)
}
func (sf *statFilter) DmStatementNumInput(filterChain *filterChain, s *DmStatement) int {
return filterChain.DmStatementNumInput(s)
}
func (sf *statFilter) DmStatementExec(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmResult, error) {
stmtExecBefore(s)
dr, err := filterChain.DmStatementExec(s, args)
if err != nil {
statementExecuteErrorAfter(s, args, err)
return nil, err
}
stmtExecAfter(s, args, int(dr.affectedRows))
return dr, nil
}
func (sf *statFilter) DmStatementExecContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmResult, error) {
stmtExecBefore(s)
dr, err := filterChain.DmStatementExecContext(s, ctx, args)
if err != nil {
statementExecuteErrorAfter(s, args, err)
return nil, err
}
stmtExecAfter(s, args, int(dr.affectedRows))
return dr, nil
}
func (sf *statFilter) DmStatementQuery(filterChain *filterChain, s *DmStatement, args []driver.Value) (*DmRows, error) {
stmtQueryBefore(s)
dr, err := filterChain.DmStatementQuery(s, args)
if err != nil {
statementExecuteErrorAfter(s, args, err)
return nil, err
}
stmtQueryAfter(s, args, dr)
return dr, nil
}
func (sf *statFilter) DmStatementQueryContext(filterChain *filterChain, s *DmStatement, ctx context.Context, args []driver.NamedValue) (*DmRows, error) {
stmtQueryBefore(s)
dr, err := filterChain.DmStatementQueryContext(s, ctx, args)
if err != nil {
statementExecuteErrorAfter(s, args, err)
return nil, err
}
stmtQueryAfter(s, args, dr)
return dr, nil
}
func (sf *statFilter) DmStatementCheckNamedValue(filterChain *filterChain, s *DmStatement, nv *driver.NamedValue) error {
return filterChain.DmStatementCheckNamedValue(s, nv)
}
//DmResult
func (sf *statFilter) DmResultLastInsertId(filterChain *filterChain, r *DmResult) (int64, error) {
return filterChain.DmResultLastInsertId(r)
}
func (sf *statFilter) DmResultRowsAffected(filterChain *filterChain, r *DmResult) (int64, error) {
return filterChain.DmResultRowsAffected(r)
}
//DmRows
func (sf *statFilter) DmRowsColumns(filterChain *filterChain, r *DmRows) []string {
return filterChain.DmRowsColumns(r)
}
func (sf *statFilter) DmRowsClose(filterChain *filterChain, r *DmRows) error {
if !r.CurrentRows.closed {
resultSetCloseBefore(r)
}
return filterChain.DmRowsClose(r)
}
func (sf *statFilter) DmRowsNext(filterChain *filterChain, r *DmRows, dest []driver.Value) error {
return filterChain.DmRowsNext(r, dest)
}
func (sf *statFilter) DmRowsHasNextResultSet(filterChain *filterChain, r *DmRows) bool {
return filterChain.DmRowsHasNextResultSet(r)
}
func (sf *statFilter) DmRowsNextResultSet(filterChain *filterChain, r *DmRows) error {
return filterChain.DmRowsNextResultSet(r)
}
func (sf *statFilter) DmRowsColumnTypeScanType(filterChain *filterChain, r *DmRows, index int) reflect.Type {
return filterChain.DmRowsColumnTypeScanType(r, index)
}
func (sf *statFilter) DmRowsColumnTypeDatabaseTypeName(filterChain *filterChain, r *DmRows, index int) string {
return filterChain.DmRowsColumnTypeDatabaseTypeName(r, index)
}
func (sf *statFilter) DmRowsColumnTypeLength(filterChain *filterChain, r *DmRows, index int) (length int64, ok bool) {
return filterChain.DmRowsColumnTypeLength(r, index)
}
func (sf *statFilter) DmRowsColumnTypeNullable(filterChain *filterChain, r *DmRows, index int) (nullable, ok bool) {
return filterChain.DmRowsColumnTypeNullable(r, index)
}
func (sf *statFilter) DmRowsColumnTypePrecisionScale(filterChain *filterChain, r *DmRows, index int) (precision, scale int64, ok bool) {
return filterChain.DmRowsColumnTypePrecisionScale(r, index)
}
func getActiveStmtCount(conn *DmConnection) int {
if conn.stmtMap == nil {
return 0
} else {
return len(conn.stmtMap)
}
}
func statementCreateAfter(conn *DmConnection, stmt *DmStatement) {
stmt.statInfo.setConstructNano()
conn.statInfo.getConnStat().incrementStmt()
}
func connExecBefore(conn *DmConnection, sql string) {
conn.statInfo.setLastExecuteSql(sql)
conn.statInfo.setFirstResultSet(false)
conn.statInfo.setLastExecuteType(ExecuteUpdate)
internalBeforeConnExecute(conn, sql)
}
func connExecAfter(conn *DmConnection, sql string, args interface{}, updateCount int) {
internalAfterConnExecute(conn, args, updateCount)
}
func connQueryBefore(conn *DmConnection, sql string) {
conn.statInfo.setLastExecuteSql(sql)
conn.statInfo.setFirstResultSet(true)
conn.statInfo.setLastExecuteType(ExecuteQuery)
internalBeforeConnExecute(conn, sql)
}
func connQueryAfter(conn *DmConnection, sql string, args interface{}, resultSet *DmRows) {
if resultSet != nil {
connResultSetCreateAfter(resultSet, conn)
}
internalAfterConnExecute(conn, args, 0)
}
func stmtExecBefore(stmt *DmStatement) {
stmt.statInfo.setLastExecuteSql(stmt.nativeSql)
stmt.statInfo.setFirstResultSet(false)
stmt.statInfo.setLastExecuteType(ExecuteUpdate)
internalBeforeStatementExecute(stmt, stmt.nativeSql)
}
func stmtExecAfter(stmt *DmStatement, args interface{}, updateCount int) {
internalAfterStatementExecute(stmt, args, updateCount)
}
func stmtQueryBefore(stmt *DmStatement) {
stmt.statInfo.setLastExecuteSql(stmt.nativeSql)
stmt.statInfo.setFirstResultSet(true)
stmt.statInfo.setLastExecuteType(ExecuteQuery)
internalBeforeStatementExecute(stmt, stmt.nativeSql)
}
func stmtQueryAfter(stmt *DmStatement, args interface{}, resultSet *DmRows) {
if resultSet != nil {
stmtResultSetCreateAfter(resultSet, stmt)
}
internalAfterStatementExecute(stmt, args, 0)
}
func internalBeforeConnExecute(conn *DmConnection, sql string) {
connStat := conn.statInfo.getConnStat()
connStat.incrementExecuteCount()
conn.statInfo.beforeExecute()
sqlStat := conn.statInfo.getSqlStat()
if sqlStat == nil || sqlStat.Removed == 1 || !(sqlStat.Sql == sql) {
sqlStat = connStat.createSqlStat(sql)
conn.statInfo.setSqlStat(sqlStat)
}
inTransaction := false
inTransaction = !conn.autoCommit
if sqlStat != nil {
sqlStat.ExecuteLastStartTime = time.Now().UnixNano()
sqlStat.incrementRunningCount()
if inTransaction {
sqlStat.incrementInTransactionCount()
}
}
}
func internalAfterConnExecute(conn *DmConnection, args interface{}, updateCount int) {
nowNano := time.Now().UnixNano()
nanos := nowNano - conn.statInfo.getLastExecuteStartNano()
conn.statInfo.afterExecute(nanos)
sqlStat := conn.statInfo.getSqlStat()
if sqlStat != nil {
sqlStat.incrementExecuteSuccessCount()
sqlStat.decrementRunningCount()
parameters := buildSlowParameters(args)
sqlStat.addExecuteTimeAndResultHoldTimeHistogramRecord(conn.statInfo.getLastExecuteType(), conn.statInfo.isFirstResultSet(),
nanos, parameters)
if !conn.statInfo.isFirstResultSet() &&
conn.statInfo.getLastExecuteType() == ExecuteUpdate {
if updateCount < 0 {
updateCount = 0
}
sqlStat.addUpdateCount(int64(updateCount))
}
}
}
func internalBeforeStatementExecute(stmt *DmStatement, sql string) {
connStat := stmt.dmConn.statInfo.getConnStat()
connStat.incrementExecuteCount()
stmt.statInfo.beforeExecute()
sqlStat := stmt.statInfo.getSqlStat()
if sqlStat == nil || sqlStat.Removed == 1 || !(sqlStat.Sql == sql) {
sqlStat = connStat.createSqlStat(sql)
stmt.statInfo.setSqlStat(sqlStat)
}
inTransaction := false
inTransaction = !stmt.dmConn.autoCommit
if sqlStat != nil {
sqlStat.ExecuteLastStartTime = time.Now().UnixNano()
sqlStat.incrementRunningCount()
if inTransaction {
sqlStat.incrementInTransactionCount()
}
}
}
func internalAfterStatementExecute(stmt *DmStatement, args interface{}, updateCount int) {
nowNano := time.Now().UnixNano()
nanos := nowNano - stmt.statInfo.getLastExecuteStartNano()
stmt.statInfo.afterExecute(nanos)
sqlStat := stmt.statInfo.getSqlStat()
if sqlStat != nil {
sqlStat.incrementExecuteSuccessCount()
sqlStat.decrementRunningCount()
parameters := ""
if stmt.paramCount > 0 {
parameters = buildStmtSlowParameters(stmt, args)
}
sqlStat.addExecuteTimeAndResultHoldTimeHistogramRecord(stmt.statInfo.getLastExecuteType(), stmt.statInfo.isFirstResultSet(),
nanos, parameters)
if (!stmt.statInfo.isFirstResultSet()) &&
stmt.statInfo.getLastExecuteType() == ExecuteUpdate {
updateCount := stmt.execInfo.updateCount
if updateCount < 0 {
updateCount = 0
}
sqlStat.addUpdateCount(updateCount)
}
}
}
func buildSlowParameters(args interface{}) string {
switch v := args.(type) {
case []driver.Value:
sb := bytes.NewBufferString("")
for i := 0; i < len(v); i++ {
if i != 0 {
sb.WriteString(",")
} else {
sb.WriteString("[")
}
sb.WriteString(fmt.Sprint(v[i]))
}
if len(v) > 0 {
sb.WriteString("]")
}
return sb.String()
case []driver.NamedValue:
sb := bytes.NewBufferString("")
for i := 0; i < len(v); i++ {
if i != 0 {
sb.WriteString(",")
} else {
sb.WriteString("[")
}
sb.WriteString(fmt.Sprint(v[i]))
}
if len(v) > 0 {
sb.WriteString("]")
}
return sb.String()
default:
return ""
}
}
func buildStmtSlowParameters(stmt *DmStatement, args interface{}) string {
switch v := args.(type) {
case []driver.Value:
sb := bytes.NewBufferString("")
for i := 0; i < int(stmt.paramCount); i++ {
if i != 0 {
sb.WriteString(",")
} else {
sb.WriteString("[")
}
sb.WriteString(fmt.Sprint(v[i]))
}
if len(v) > 0 {
sb.WriteString("]")
}
return sb.String()
case []driver.NamedValue:
sb := bytes.NewBufferString("")
for i := 0; i < int(stmt.paramCount); i++ {
if i != 0 {
sb.WriteString(",")
} else {
sb.WriteString("[")
}
sb.WriteString(fmt.Sprint(v[i]))
}
if len(v) > 0 {
sb.WriteString("]")
}
return sb.String()
default:
return ""
}
}
func connExecuteErrorAfter(conn *DmConnection, args interface{}, err error) {
nanos := time.Now().UnixNano() - conn.statInfo.getLastExecuteStartNano()
conn.statInfo.getConnStat().incrementErrorCount()
conn.statInfo.afterExecute(nanos)
// SQL
sqlStat := conn.statInfo.getSqlStat()
if sqlStat != nil {
sqlStat.decrementRunningCount()
sqlStat.error(err)
parameters := buildSlowParameters(args)
sqlStat.addExecuteTimeAndResultHoldTimeHistogramRecord(conn.statInfo.getLastExecuteType(), conn.statInfo.isFirstResultSet(),
nanos, parameters)
}
}
func statementExecuteErrorAfter(stmt *DmStatement, args interface{}, err error) {
nanos := time.Now().UnixNano() - stmt.statInfo.getLastExecuteStartNano()
stmt.dmConn.statInfo.getConnStat().incrementErrorCount()
stmt.statInfo.afterExecute(nanos)
// SQL
sqlStat := stmt.statInfo.getSqlStat()
if sqlStat != nil {
sqlStat.decrementRunningCount()
sqlStat.error(err)
parameters := ""
if stmt.paramCount > 0 {
parameters = buildStmtSlowParameters(stmt, args)
}
sqlStat.addExecuteTimeAndResultHoldTimeHistogramRecord(stmt.statInfo.getLastExecuteType(), stmt.statInfo.isFirstResultSet(),
nanos, parameters)
}
}
func statementCloseBefore(stmt *DmStatement) {
stmt.dmConn.statInfo.getConnStat().decrementStmt()
}
func connResultSetCreateAfter(dmdbResultSet *DmRows, conn *DmConnection) {
dmdbResultSet.statInfo.setSql(conn.statInfo.getLastExecuteSql())
dmdbResultSet.statInfo.setSqlStat(conn.statInfo.getSqlStat())
dmdbResultSet.statInfo.setConstructNano()
}
func stmtResultSetCreateAfter(dmdbResultSet *DmRows, stmt *DmStatement) {
dmdbResultSet.statInfo.setSql(stmt.statInfo.getLastExecuteSql())
dmdbResultSet.statInfo.setSqlStat(stmt.statInfo.getSqlStat())
dmdbResultSet.statInfo.setConstructNano()
}
func resultSetCloseBefore(resultSet *DmRows) {
nanos := time.Now().UnixNano() - resultSet.statInfo.getConstructNano()
fetchRowCount := getFetchedRows(resultSet)
sqlStat := resultSet.statInfo.getSqlStat()
if sqlStat != nil && resultSet.statInfo.getCloseCount() == 0 {
sqlStat.addFetchRowCount(fetchRowCount)
stmtExecuteNano := resultSet.statInfo.getLastExecuteTimeNano()
sqlStat.addResultSetHoldTimeNano2(stmtExecuteNano, nanos)
if resultSet.statInfo.getReadStringLength() > 0 {
sqlStat.addStringReadLength(resultSet.statInfo.getReadStringLength())
}
if resultSet.statInfo.getReadBytesLength() > 0 {
sqlStat.addReadBytesLength(resultSet.statInfo.getReadBytesLength())
}
if resultSet.statInfo.getOpenInputStreamCount() > 0 {
sqlStat.addInputStreamOpenCount(int64(resultSet.statInfo.getOpenInputStreamCount()))
}
if resultSet.statInfo.getOpenReaderCount() > 0 {
sqlStat.addReaderOpenCount(int64(resultSet.statInfo.getOpenReaderCount()))
}
}
resultSet.statInfo.incrementCloseCount()
}
func getFetchedRows(rs *DmRows) int64 {
if rs.CurrentRows.currentPos >= rs.CurrentRows.totalRowCount {
return rs.CurrentRows.totalRowCount
} else {
return rs.CurrentRows.currentPos + 1
}
}
+1017
View File
File diff suppressed because it is too large Load Diff
+137
View File
@@ -0,0 +1,137 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
const (
LOB_FLAG_BYTE = 0
LOB_FLAG_CHAR = 1
LOB_IN_ROW = 0x1
LOB_OFF_ROW = 0x2
NBLOB_HEAD_IN_ROW_FLAG = 0
NBLOB_HEAD_BLOBID = NBLOB_HEAD_IN_ROW_FLAG + BYTE_SIZE
NBLOB_HEAD_BLOB_LEN = NBLOB_HEAD_BLOBID + DDWORD_SIZE
NBLOB_HEAD_OUTROW_GROUPID = NBLOB_HEAD_BLOB_LEN + ULINT_SIZE
NBLOB_HEAD_OUTROW_FILEID = NBLOB_HEAD_OUTROW_GROUPID + USINT_SIZE
NBLOB_HEAD_OUTROW_PAGENO = NBLOB_HEAD_OUTROW_FILEID + USINT_SIZE
NBLOB_EX_HEAD_TABLE_ID = NBLOB_HEAD_OUTROW_PAGENO + ULINT_SIZE
NBLOB_EX_HEAD_COL_ID = NBLOB_EX_HEAD_TABLE_ID + ULINT_SIZE
NBLOB_EX_HEAD_ROW_ID = NBLOB_EX_HEAD_COL_ID + USINT_SIZE
NBLOB_EX_HEAD_FPA_GRPID = NBLOB_EX_HEAD_ROW_ID + LINT64_SIZE
NBLOB_EX_HEAD_FPA_FILEID = NBLOB_EX_HEAD_FPA_GRPID + USINT_SIZE
NBLOB_EX_HEAD_FPA_PAGENO = NBLOB_EX_HEAD_FPA_FILEID + USINT_SIZE
NBLOB_EX_HEAD_SIZE = NBLOB_EX_HEAD_FPA_PAGENO + ULINT_SIZE
NBLOB_OUTROW_HEAD_SIZE = NBLOB_HEAD_OUTROW_PAGENO + ULINT_SIZE
NBLOB_INROW_HEAD_SIZE = NBLOB_HEAD_BLOB_LEN + ULINT_SIZE
)
type lob struct {
blobId int64
inRow bool
groupId int16
fileId int16
pageNo int32
tabId int32
colId int16
rowId int64
exGroupId int16
exFileId int16
exPageNo int32
curFileId int16
curPageNo int32
curPageOffset int16
totalOffset int32
readOver bool
connection *DmConnection
local bool
updateable bool
lobFlag int8
length int64
compatibleOracle bool
fetchAll bool
freed bool
modify bool
Valid bool
}
func (lob *lob) GetLength() (int64, error) {
var err error
if err = lob.checkValid(); err != nil {
return -1, err
}
if err = lob.checkFreed(); err != nil {
return -1, err
}
if lob.length == -1 {
if lob.length, err = lob.connection.Access.dm_build_585(lob); err != nil {
return -1, err
}
}
return lob.length, nil
}
func (lob *lob) resetCurrentInfo() {
lob.curFileId = lob.fileId
lob.curPageNo = lob.pageNo
lob.totalOffset = 0
lob.curPageOffset = 0
}
func (lob *lob) getLengthFromHead(head []byte) int64 {
return int64(Dm_build_1346.Dm_build_1448(head, NBLOB_HEAD_BLOB_LEN))
}
func (lob *lob) canOptimized(connection *DmConnection) bool {
return !(lob.inRow || lob.fetchAll || lob.local || connection != lob.connection)
}
func (lob *lob) buildCtlData() (bytes []byte) {
if lob.connection.NewLobFlag {
bytes = make([]byte, NBLOB_EX_HEAD_SIZE, NBLOB_EX_HEAD_SIZE)
} else {
bytes = make([]byte, NBLOB_OUTROW_HEAD_SIZE, NBLOB_OUTROW_HEAD_SIZE)
}
Dm_build_1346.Dm_build_1347(bytes, NBLOB_HEAD_IN_ROW_FLAG, LOB_OFF_ROW)
Dm_build_1346.Dm_build_1367(bytes, NBLOB_HEAD_BLOBID, lob.blobId)
Dm_build_1346.Dm_build_1362(bytes, NBLOB_HEAD_BLOB_LEN, -1)
Dm_build_1346.Dm_build_1357(bytes, NBLOB_HEAD_OUTROW_GROUPID, lob.groupId)
Dm_build_1346.Dm_build_1357(bytes, NBLOB_HEAD_OUTROW_FILEID, lob.fileId)
Dm_build_1346.Dm_build_1362(bytes, NBLOB_HEAD_OUTROW_PAGENO, lob.pageNo)
if lob.connection.NewLobFlag {
Dm_build_1346.Dm_build_1362(bytes, NBLOB_EX_HEAD_TABLE_ID, lob.tabId)
Dm_build_1346.Dm_build_1357(bytes, NBLOB_EX_HEAD_COL_ID, lob.colId)
Dm_build_1346.Dm_build_1367(bytes, NBLOB_EX_HEAD_ROW_ID, lob.rowId)
Dm_build_1346.Dm_build_1357(bytes, NBLOB_EX_HEAD_FPA_GRPID, lob.exGroupId)
Dm_build_1346.Dm_build_1357(bytes, NBLOB_EX_HEAD_FPA_FILEID, lob.exFileId)
Dm_build_1346.Dm_build_1362(bytes, NBLOB_EX_HEAD_FPA_PAGENO, lob.exPageNo)
}
return
}
func (lob *lob) checkFreed() (err error) {
if lob.freed {
err = ECGO_LOB_FREED.throw()
}
return
}
func (lob *lob) checkValid() error {
if !lob.Valid {
return ECGO_IS_NULL.throw()
}
return nil
}
+25
View File
@@ -0,0 +1,25 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
const (
ParamDataEnum_Null = 0
/**
* 只有大字段才有行内数据、行外数据的概念
*/
ParamDataEnum_OFF_ROW = 1
)
// JDBC中的Data
type lobCtl struct {
value []byte
}
// lob数据返回信息,自bug610335后,服务器不光返回字节数组,还返回字符数
type lobRetInfo struct {
charLen int64 // 字符长度
data []byte //lob数据
}
+124
View File
@@ -0,0 +1,124 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"fmt"
"os"
"strconv"
"strings"
"time"
"gitee.com/chunanyong/dm/util"
)
const (
MAX_FILE_SIZE = 100 * 1024 * 1024
FLUSH_SIZE = 32 * 1024
)
type goRun interface {
doRun()
}
type logWriter struct {
flushQueue chan []byte
date string
logFile *os.File
flushFreq int
filePath string
filePrefix string
buffer *Dm_build_0
}
func (lw *logWriter) doRun() {
defer func() {
lw.beforeExit()
lw.closeCurrentFile()
}()
i := 0
for {
var ibytes []byte
select {
case ibytes = <-lw.flushQueue:
if LogLevel != LOG_OFF {
if i == LogFlushQueueSize {
lw.doFlush(lw.buffer)
i = 0
} else {
lw.buffer.Dm_build_26(ibytes, 0, len(ibytes))
i++
}
}
case <-time.After(time.Duration(LogFlushFreq) * time.Millisecond):
if LogLevel != LOG_OFF && lw.buffer.Dm_build_5() > 0 {
lw.doFlush(lw.buffer)
i = 0
}
}
}
}
func (lw *logWriter) doFlush(buffer *Dm_build_0) {
if lw.needCreateNewFile() {
lw.closeCurrentFile()
lw.logFile = lw.createNewFile()
}
if lw.logFile != nil {
buffer.Dm_build_20(lw.logFile, buffer.Dm_build_5())
}
}
func (lw *logWriter) closeCurrentFile() {
if lw.logFile != nil {
lw.logFile.Close()
lw.logFile = nil
}
}
func (lw *logWriter) createNewFile() *os.File {
lw.date = time.Now().Format("2006-01-02")
fileName := lw.filePrefix + "_" + lw.date + "_" + strconv.Itoa(time.Now().Nanosecond()) + ".log"
lw.filePath = LogDir
if len(lw.filePath) > 0 {
if _, err := os.Stat(lw.filePath); err != nil {
os.MkdirAll(lw.filePath, 0755)
}
if _, err := os.Stat(lw.filePath + fileName); err != nil {
logFile, err := os.Create(lw.filePath + fileName)
if err != nil {
fmt.Println(err)
return nil
}
return logFile
}
}
return nil
}
func (lw *logWriter) needCreateNewFile() bool {
now := time.Now().Format("2006-01-02")
fileInfo, err := lw.logFile.Stat()
return now != lw.date || err != nil || lw.logFile == nil || fileInfo.Size() > int64(MAX_FILE_SIZE)
}
func (lw *logWriter) beforeExit() {
close(lw.flushQueue)
var ibytes []byte
for ibytes = <-lw.flushQueue; ibytes != nil; ibytes = <-lw.flushQueue {
lw.buffer.Dm_build_26(ibytes, 0, len(ibytes))
if lw.buffer.Dm_build_5() >= LogBufferSize {
lw.doFlush(lw.buffer)
}
}
if lw.buffer.Dm_build_5() > 0 {
lw.doFlush(lw.buffer)
}
}
func (lw *logWriter) WriteLine(msg string) {
var b = []byte(strings.TrimSpace(msg) + util.LINE_SEPARATOR)
lw.flushQueue <- b
}
+2944
View File
File diff suppressed because it is too large Load Diff
+205
View File
@@ -0,0 +1,205 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"io"
)
const (
READ_LEN = Dm_build_820
)
type iOffRowBinder interface {
read(buf *Dm_build_0)
isReadOver() bool
getObj() interface{}
}
type offRowBinder struct {
obj interface{}
encoding string
readOver bool
buffer *Dm_build_0
position int32
offRow bool
targetLength int64
}
func newOffRowBinder(obj interface{}, encoding string, targetLength int64) *offRowBinder {
return &offRowBinder{
obj: obj,
encoding: encoding,
targetLength: targetLength,
readOver: false,
buffer: Dm_build_4(),
position: 0,
}
}
type offRowBytesBinder struct {
*offRowBinder
}
func newOffRowBytesBinder(obj []byte, encoding string) *offRowBytesBinder {
var binder = &offRowBytesBinder{
newOffRowBinder(obj, encoding, int64(IGNORE_TARGET_LENGTH)),
}
binder.read(binder.buffer)
binder.offRow = binder.buffer.Dm_build_5() > Dm_build_817
return binder
}
func (b *offRowBytesBinder) read(buf *Dm_build_0) {
if b.buffer.Dm_build_5() > 0 {
buf.Dm_build_37(b.buffer)
} else if !b.readOver {
var obj = b.obj.([]byte)
buf.Dm_build_26(obj, 0, len(obj))
b.readOver = true
}
}
func (b *offRowBytesBinder) isReadOver() bool {
return b.readOver
}
func (b *offRowBytesBinder) getObj() interface{} {
return b.obj
}
type offRowBlobBinder struct {
*offRowBinder
}
func newOffRowBlobBinder(blob DmBlob, encoding string) *offRowBlobBinder {
var binder = &offRowBlobBinder{
newOffRowBinder(blob, encoding, int64(IGNORE_TARGET_LENGTH)),
}
binder.read(binder.buffer)
binder.offRow = binder.buffer.Dm_build_5() > Dm_build_817
return binder
}
func (b *offRowBlobBinder) read(buf *Dm_build_0) {
if b.buffer.Dm_build_5() > 0 {
buf.Dm_build_37(b.buffer)
} else if !b.readOver {
var obj = b.obj.(DmBlob)
var totalLen, _ = obj.GetLength()
var leaveLen = totalLen - int64(b.position)
var readLen = int32(leaveLen)
if leaveLen > READ_LEN {
readLen = READ_LEN
}
var bytes, _ = obj.getBytes(int64(b.position)+1, readLen)
b.position += readLen
if b.position == int32(totalLen) {
b.readOver = true
}
buf.Dm_build_26(bytes, 0, len(bytes))
}
}
func (b *offRowBlobBinder) isReadOver() bool {
return b.readOver
}
func (b *offRowBlobBinder) getObj() interface{} {
return b.obj
}
type offRowClobBinder struct {
*offRowBinder
}
func newOffRowClobBinder(clob DmClob, encoding string) *offRowClobBinder {
var binder = &offRowClobBinder{
newOffRowBinder(clob, encoding, int64(IGNORE_TARGET_LENGTH)),
}
binder.read(binder.buffer)
binder.offRow = binder.buffer.Dm_build_5() > Dm_build_817
return binder
}
func (b *offRowClobBinder) read(buf *Dm_build_0) {
if b.buffer.Dm_build_5() > 0 {
buf.Dm_build_37(b.buffer)
} else if !b.readOver {
var obj = b.obj.(DmClob)
var totalLen, _ = obj.GetLength()
var leaveLen = totalLen - int64(b.position)
var readLen = int32(leaveLen)
if leaveLen > READ_LEN {
readLen = READ_LEN
}
var str, _ = obj.getSubString(int64(b.position)+1, readLen)
var bytes = Dm_build_1346.Dm_build_1562(str, b.encoding, nil)
b.position += readLen
if b.position == int32(totalLen) {
b.readOver = true
}
buf.Dm_build_26(bytes, 0, len(bytes))
}
}
func (b *offRowClobBinder) isReadOver() bool {
return b.readOver
}
func (b *offRowClobBinder) getObj() interface{} {
return b.obj
}
type offRowReaderBinder struct {
*offRowBinder
}
func newOffRowReaderBinder(reader io.Reader, encoding string) *offRowReaderBinder {
var binder = &offRowReaderBinder{
newOffRowBinder(reader, encoding, int64(IGNORE_TARGET_LENGTH)),
}
binder.read(binder.buffer)
binder.offRow = binder.buffer.Dm_build_5() > Dm_build_817
return binder
}
func (b *offRowReaderBinder) read(buf *Dm_build_0) {
if b.buffer.Dm_build_5() > 0 {
buf.Dm_build_37(b.buffer)
} else if !b.readOver {
var err error
var readLen = READ_LEN
var reader = b.obj.(io.Reader)
var bytes = make([]byte, readLen)
readLen, err = reader.Read(bytes)
if err == io.EOF {
b.readOver = true
return
}
b.position += int32(readLen)
if readLen < len(bytes) || b.targetLength != int64(IGNORE_TARGET_LENGTH) && int64(b.position) == b.targetLength {
b.readOver = true
}
buf.Dm_build_26(bytes[0:readLen], 0, readLen)
}
}
func (b *offRowReaderBinder) readAll() []byte {
var byteArray = Dm_build_4()
b.read(byteArray)
for !b.readOver {
b.read(byteArray)
}
return byteArray.Dm_build_47()
}
func (b *offRowReaderBinder) isReadOver() bool {
return b.readOver
}
func (b *offRowReaderBinder) getObj() interface{} {
return b.obj
}
+882
View File
@@ -0,0 +1,882 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"fmt"
"math"
"strconv"
"strings"
"time"
"unicode"
"unicode/utf8"
"gitee.com/chunanyong/dm/util"
)
type oracleDateFormat struct {
PM bool
TZNegative bool
pattern string
language int
scale int32
FormatElementList []interface{}
YearElement yearElement
MonthElement monthElement
MonElement monElement
MMElement mmElement
DDElement ddElement
HH24Element hh24Element
HH12Element hh12Element
MIElement miElement
SSElement ssElement
FElement fElement
TZHElement tzhElement
TZMElement tzmElement
AMElement amElement
}
type element interface {
/**
* 从字符串中解析出对应的值,
* @param str 完整的字符串
* @param offset 当前偏移
* @return 解析后的offset
*/
parse(str string, offset int, dt []int) (int, error)
/**
* 将时间值value格式化成字符串
*/
format(dt []int) string
}
type yearElement struct {
OracleDateFormat *oracleDateFormat
len int
}
func (YearElement yearElement) parse(str string, offset int, dt []int) (int, error) {
strLen := 0
for i := offset; i < offset+YearElement.len && i < len(str); i++ {
if !unicode.IsLetter(rune(str[i])) && !unicode.IsDigit(rune(str[i])) {
break
}
strLen++
}
str = str[offset : offset+strLen]
if YearElement.len < 4 {
today := strconv.FormatInt(int64(dt[OFFSET_YEAR]), 10)
i, err := strconv.ParseInt(today[:4-YearElement.len]+str, 10, 32)
if err != nil {
return 0, err
}
dt[OFFSET_YEAR] = int(i)
} else {
i, err := strconv.ParseInt(str, 10, 32)
if err != nil {
return 0, err
}
dt[OFFSET_YEAR] = int(i)
}
return offset + strLen, nil
}
func (YearElement yearElement) format(dt []int) string {
return YearElement.OracleDateFormat.formatInt(dt[OFFSET_YEAR], YearElement.len)
}
type monthElement struct {
OracleDateFormat *oracleDateFormat
upperCase bool
lowerCase bool
}
var monthNameList = []string{"", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}
func (MonthElement monthElement) parse(str string, offset int, dt []int) (int, error) {
if MonthElement.OracleDateFormat.language == LANGUAGE_CN {
index := strings.IndexRune(str[offset:], '月')
if index == -1 {
return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
}
index += offset
mon, err := strconv.ParseInt(str[offset:index], 10, 32)
if err != nil {
return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
}
if mon > 12 || mon < 1 {
return -1, ECGO_INVALID_DATETIME_VALUE.throw()
}
dt[OFFSET_MONTH] = int(mon)
return index + utf8.RuneLen('月'), nil
} else {
str = str[offset:]
mon := 0
for i := 1; i < len(monthNameList); i++ {
if util.StringUtil.StartWithIgnoreCase(str, monthNameList[i]) {
mon = i
break
}
}
if mon == 0 {
return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
}
dt[OFFSET_MONTH] = mon
return offset + len(monthNameList[mon]), nil
}
}
func (MonthElement monthElement) format(dt []int) string {
value := dt[OFFSET_MONTH]
if MonthElement.OracleDateFormat.language == LANGUAGE_CN {
return strconv.FormatInt(int64(value), 10) + "月"
}
if MonthElement.upperCase {
return strings.ToUpper(monthNameList[value])
} else if MonthElement.lowerCase {
return strings.ToLower(monthNameList[value])
} else {
return monthNameList[value]
}
}
type monElement struct {
OracleDateFormat *oracleDateFormat
upperCase bool
lowerCase bool
}
var monNameList []string = []string{"", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}
func (MonElement monElement) parse(str string, offset int, dt []int) (int, error) {
if MonElement.OracleDateFormat.language == LANGUAGE_CN {
index := strings.IndexRune(str[offset:], '月') + offset
if index == -1+offset {
return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
}
mon, err := strconv.ParseInt(str[offset:index], 10, 32)
if err != nil {
return -1, err
}
if mon > 12 || mon < 1 {
return -1, ECGO_INVALID_DATETIME_VALUE.throw()
}
dt[OFFSET_MONTH] = int(mon)
return index + utf8.RuneLen('月'), nil
} else {
str = str[offset : offset+3]
mon := 0
for i := 1; i < len(monNameList); i++ {
if util.StringUtil.EqualsIgnoreCase(str, monNameList[i]) {
mon = i
break
}
}
if mon == 0 {
return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
}
dt[OFFSET_MONTH] = mon
return offset + 3, nil
}
}
func (MonElement monElement) format(dt []int) string {
value := dt[OFFSET_MONTH]
language := int(0)
if language == LANGUAGE_CN {
return strconv.FormatInt(int64(value), 10) + "月"
}
if MonElement.upperCase {
return strings.ToUpper(monNameList[value])
} else if MonElement.lowerCase {
return strings.ToLower(monNameList[value])
} else {
return monNameList[value]
}
}
type mmElement struct {
OracleDateFormat *oracleDateFormat
}
func (MMElement mmElement) parse(str string, offset int, dt []int) (int, error) {
strLen := 0
for i := offset; i < offset+2 && i < len(str); i++ {
if !unicode.IsLetter(rune(str[i])) && !unicode.IsDigit(rune(str[i])) {
break
}
strLen++
}
str = str[offset : offset+strLen]
month, err := strconv.ParseInt(str, 10, 32)
if err != nil {
return -1, ECGO_INVALID_DATETIME_FORMAT.throw()
}
if month > 12 || month < 1 {
return -1, ECGO_INVALID_DATETIME_VALUE.throw()
}
dt[OFFSET_MONTH] = int(month)
return offset + strLen, nil
}
func (MMElement mmElement) format(dt []int) string {
return MMElement.OracleDateFormat.formatInt(dt[OFFSET_MONTH], 2)
}
type ddElement struct {
OracleDateFormat *oracleDateFormat
}
func (DDElement ddElement) parse(str string, offset int, dt []int) (int, error) {
strLen := 0
for i := offset; i < offset+2 && i < len(str); i++ {
if !unicode.IsLetter(rune(str[i])) && !unicode.IsDigit(rune(str[i])) {
break
}
strLen++
}
str = str[offset : offset+strLen]
day, err := strconv.ParseInt(str, 10, 32)
if err != nil {
return -1, err
}
if day > 31 || day < 1 {
return -1, ECGO_INVALID_DATETIME_VALUE.throw()
}
dt[OFFSET_DAY] = int(day)
return offset + strLen, nil
}
func (DDElement ddElement) format(dt []int) string {
return DDElement.OracleDateFormat.formatInt(dt[OFFSET_DAY], 2)
}
type hh24Element struct {
OracleDateFormat *oracleDateFormat
}
func (HH24Element hh24Element) parse(str string, offset int, dt []int) (int, error) {
strLen := 0
for i := offset; i < offset+2 && i < len(str); i++ {
if !unicode.IsLetter(rune(str[i])) && !unicode.IsDigit(rune(str[i])) {
break
}
strLen++
}
str = str[offset : offset+strLen]
hour, err := strconv.ParseInt(str, 10, 32)
if err != nil {
return -1, err
}
if hour > 23 || hour < 0 {
return -1, ECGO_INVALID_DATETIME_VALUE.throw()
}
dt[OFFSET_HOUR] = int(hour) // 0-23
return offset + strLen, nil
}
func (HH24Element hh24Element) format(dt []int) string {
return HH24Element.OracleDateFormat.formatInt(dt[OFFSET_HOUR], 2) // 0-23
}
type hh12Element struct {
OracleDateFormat *oracleDateFormat
}
func (HH12Element hh12Element) parse(str string, offset int, dt []int) (int, error) {
strLen := 0
for i := offset; i < offset+2 && i < len(str); i++ {
if !unicode.IsLetter(rune(str[i])) && !unicode.IsDigit(rune(str[i])) {
break
}
strLen++
}
str = str[offset : offset+strLen]
hour, err := strconv.ParseInt(str, 10, 32)
if err != nil {
return -1, err
}
if hour > 12 || hour < 1 {
return -1, ECGO_INVALID_DATETIME_VALUE.throw()
}
dt[OFFSET_HOUR] = int(hour)
return offset + strLen, nil
}
func (HH12Element hh12Element) format(dt []int) string {
var ret string
value := dt[OFFSET_HOUR]
if value > 12 || value == 0 {
ret = HH12Element.OracleDateFormat.formatInt(int(math.Abs(float64(value-12))), 2) // 1-12
} else {
ret = HH12Element.OracleDateFormat.formatInt(value, 2)
}
return ret
}
type miElement struct {
OracleDateFormat *oracleDateFormat
}
func (MIElement miElement) parse(str string, offset int, dt []int) (int, error) {
strLen := 0
for i := offset; i < offset+2 && i < len(str); i++ {
if !unicode.IsLetter(rune(str[i])) && !unicode.IsDigit(rune(str[i])) {
break
}
strLen++
}
str = str[offset : offset+strLen]
minute, err := strconv.ParseInt(str, 10, 32)
if err != nil {
return -1, err
}
if minute > 59 || minute < 0 {
return -1, ECGO_INVALID_DATETIME_VALUE.throw()
}
dt[OFFSET_MINUTE] = int(minute) // 0-59
return offset + strLen, nil
}
func (MIElement miElement) format(dt []int) string {
return MIElement.OracleDateFormat.formatInt(dt[OFFSET_MINUTE], 2) // 0-59
}
type ssElement struct {
OracleDateFormat *oracleDateFormat
}
func (SSElement ssElement) parse(str string, offset int, dt []int) (int, error) {
strLen := 0
for i := offset; i < offset+2 && i < len(str); i++ {
if !unicode.IsLetter(rune(str[i])) && !unicode.IsDigit(rune(str[i])) {
break
}
strLen++
}
str = str[offset : offset+strLen]
second, err := strconv.ParseInt(str, 10, 32)
if err != nil {
return -1, err
}
if second > 59 || second < 0 {
return -1, ECGO_INVALID_DATETIME_VALUE.throw()
}
dt[OFFSET_SECOND] = int(second) // 0-59
return offset + strLen, nil
}
func (SSElement ssElement) format(dt []int) string {
return SSElement.OracleDateFormat.formatInt(dt[OFFSET_SECOND], 2) // 0-59
}
type fElement struct {
OracleDateFormat *oracleDateFormat
len int
}
func (FElement fElement) parse(str string, offset int, dt []int) (int, error) {
strLen := 0
maxLen := 0
if FElement.len > 0 {
maxLen = FElement.len
} else {
maxLen = NANOSECOND_DIGITS
}
for i := offset; i < offset+maxLen && i < len(str); i++ {
if !unicode.IsLetter(rune(str[i])) && !unicode.IsDigit(rune(str[i])) {
break
}
strLen++
}
str = str[offset : offset+strLen]
ms, err := strconv.ParseInt(str, 10, 32)
if err != nil {
return -1, err
}
if strLen < NANOSECOND_DIGITS {
ms *= int64(math.Pow10(NANOSECOND_DIGITS - strLen))
} else {
ms /= int64(math.Pow10(strLen - NANOSECOND_DIGITS))
}
dt[OFFSET_NANOSECOND] = int(ms)
return offset + strLen, nil
}
func (FElement fElement) format(dt []int) string {
msgLen := 0
if FElement.len > 0 {
msgLen = FElement.len
} else {
msgLen = int(FElement.OracleDateFormat.scale)
}
return FElement.OracleDateFormat.formatMilliSecond(dt[OFFSET_NANOSECOND], msgLen)
}
type tzhElement struct {
OracleDateFormat *oracleDateFormat
}
func (TZHElement tzhElement) parse(str string, offset int, dt []int) (int, error) {
if str[offset] == '+' {
offset += 1
} else if str[offset] == '-' {
offset += 1
TZHElement.OracleDateFormat.TZNegative = true
}
strLen := 0
for i := offset; i < offset+2 && i < len(str); i++ {
if !unicode.IsLetter(rune(str[i])) && !unicode.IsDigit(rune(str[i])) {
break
}
strLen++
}
str = str[offset : offset+strLen]
tzh, err := strconv.ParseInt(str, 10, 32)
if err != nil {
return -1, err
}
if tzh > 23 || tzh < 0 {
return -1, ECGO_INVALID_DATETIME_VALUE.throw()
}
tzh *= 60
if dt[OFFSET_TIMEZONE] == int(INVALID_VALUE) {
dt[OFFSET_TIMEZONE] = int(tzh)
} else {
dt[OFFSET_TIMEZONE] += int(tzh)
}
return offset + strLen, nil
}
func (TZHElement tzhElement) format(dt []int) string {
var value int
if dt[OFFSET_TIMEZONE] != int(INVALID_VALUE) {
value = int(math.Abs(float64(dt[OFFSET_TIMEZONE]))) / 60
} else {
value = 0
}
return TZHElement.OracleDateFormat.formatInt(value, 2)
}
type tzmElement struct {
OracleDateFormat *oracleDateFormat
}
func (TZMElement tzmElement) parse(str string, offset int, dt []int) (int, error) {
if str[offset] == '+' {
offset += 1
} else if str[offset] == '-' {
offset += 1
TZMElement.OracleDateFormat.TZNegative = true
}
strLen := 0
for i := offset; i < offset+2 && i < len(str); i++ {
if !unicode.IsLetter(rune(str[i])) && !unicode.IsDigit(rune(str[i])) {
break
}
strLen++
}
str = str[offset : offset+strLen]
tzm, err := strconv.ParseInt(str, 10, 32)
if err != nil {
return -1, err
}
if tzm > 59 || tzm < 0 {
return -1, ECGO_INVALID_DATETIME_VALUE.throw()
}
if dt[OFFSET_TIMEZONE] == INVALID_VALUE {
dt[OFFSET_TIMEZONE] = int(tzm)
} else {
dt[OFFSET_TIMEZONE] += int(tzm)
}
return offset + strLen, nil
}
func (TZMElement tzmElement) format(dt []int) string {
var value int
if dt[OFFSET_TIMEZONE] != int(INVALID_VALUE) {
value = int(math.Abs(float64(dt[OFFSET_TIMEZONE]))) % 60
} else {
value = 0
}
return TZMElement.OracleDateFormat.formatInt(value, 2)
}
type amElement struct {
OracleDateFormat *oracleDateFormat
}
func (AMElement amElement) parse(str string, offset int, dt []int) (int, error) {
runeStr := ([]rune(str))[offset : offset+2]
if AMElement.OracleDateFormat.language == LANGUAGE_CN {
if util.StringUtil.EqualsIgnoreCase("下午", string(runeStr)) {
AMElement.OracleDateFormat.PM = true
return offset + utf8.RuneLen('下') + utf8.RuneLen('午'), nil
} else {
AMElement.OracleDateFormat.PM = false
return offset + utf8.RuneLen('上') + utf8.RuneLen('午'), nil
}
} else if util.StringUtil.EqualsIgnoreCase("PM", string(runeStr)) {
AMElement.OracleDateFormat.PM = true
} else {
AMElement.OracleDateFormat.PM = false
}
return offset + 2, nil
}
func (AMElement amElement) format(dt []int) string {
hour := dt[OFFSET_HOUR]
language := int(0)
if language == LANGUAGE_CN {
if hour > 12 {
return "下午"
} else {
return "上午"
}
}
if hour > 12 {
return "PM"
} else {
return "AM"
}
}
/**
* 将int值格式化成指定长度,长度不足前面补0,长度超过的取末尾指定长度
*/
func (OracleDateFormat *oracleDateFormat) formatInt(value int, len int) string {
pow := int(math.Pow10(len))
if value >= pow {
value %= pow
}
value += pow
return strconv.FormatInt(int64(value), 10)[1:]
}
/**
* 格式化毫秒值
* @param ms
* @param len <= 6
*/
func (OracleDateFormat *oracleDateFormat) formatMilliSecond(ms int, len int) string {
var ret string
if ms < 10 {
ret = "00000" + strconv.FormatInt(int64(ms), 10)
} else if ms < 100 {
ret = "0000" + strconv.FormatInt(int64(ms), 10)
} else if ms < 1000 {
ret = "000" + strconv.FormatInt(int64(ms), 10)
} else if ms < 10000 {
ret = "00" + strconv.FormatInt(int64(ms), 10)
} else if ms < 100000 {
ret = "0" + strconv.FormatInt(int64(ms), 10)
} else {
ret = strconv.FormatInt(int64(ms), 10)
}
if len < 6 {
ret = ret[:len]
}
return ret
}
func getFormat() *oracleDateFormat {
format := new(oracleDateFormat)
format.PM = false
format.TZNegative = false
format.YearElement = yearElement{format, 4}
format.MonthElement = monthElement{format, false, false}
format.MonElement = monElement{format, false, false}
format.MMElement = mmElement{format}
format.DDElement = ddElement{format}
format.HH24Element = hh24Element{format}
format.HH12Element = hh12Element{format}
format.MIElement = miElement{format}
format.SSElement = ssElement{format}
format.FElement = fElement{format, -1}
format.TZHElement = tzhElement{format}
format.TZMElement = tzmElement{format}
format.AMElement = amElement{format}
return format
}
func (OracleDateFormat *oracleDateFormat) parse(str string) (ret []int, err error) {
defer func() {
if p := recover(); p != nil {
err = ECGO_INVALID_DATETIME_FORMAT.throw()
}
}()
OracleDateFormat.TZNegative = false
OracleDateFormat.PM = false
dt := make([]int, DT_LEN)
// oracle默认年月日为 当前时间
today := time.Now()
dt[OFFSET_YEAR] = today.Year()
dt[OFFSET_MONTH] = int(today.Month())
dt[OFFSET_DAY] = today.Day()
dt[OFFSET_TIMEZONE] = INVALID_VALUE
offset := 0
str = strings.TrimSpace(str)
for _, obj := range OracleDateFormat.FormatElementList {
// 跳过空格
for str[offset] == ' ' && fmt.Sprintf("%+v", obj) != " " {
offset++
}
if e, ok := obj.(element); ok {
offset, err = e.parse(str, offset, dt)
if err != nil {
return nil, err
}
} else {
offset += len(obj.(string))
}
}
if offset < len(str) {
//[6103]:文字与格式字符串不匹配.
return nil, ECGO_INVALID_DATETIME_VALUE.throw()
}
// 12小时制时间转换
if OracleDateFormat.PM {
dt[OFFSET_HOUR] = (dt[OFFSET_HOUR] + 12) % 24
}
// 时区符号保留
if OracleDateFormat.TZNegative {
dt[OFFSET_TIMEZONE] = -dt[OFFSET_TIMEZONE]
}
// check day
if dt[OFFSET_DAY] > getDaysOfMonth(dt[OFFSET_YEAR], dt[OFFSET_MONTH]) || dt[OFFSET_DAY] < 1 {
return nil, ECGO_INVALID_DATETIME_VALUE.throw()
}
// check timezone 兼容oracle
if dt[OFFSET_TIMEZONE] != INVALID_VALUE && (dt[OFFSET_TIMEZONE] > 14*60 || dt[OFFSET_TIMEZONE] <= -13*60) {
return nil, ECGO_INVALID_DATETIME_VALUE.throw()
}
return dt, nil
}
func parse(str string, pattern string, language int) ([]int, error) {
f := getFormat()
f.setPattern(pattern)
f.language = language
return f.parse(str)
}
func (OracleDateFormat *oracleDateFormat) setPattern(pattern string) {
if pattern != OracleDateFormat.pattern {
OracleDateFormat.pattern = pattern
OracleDateFormat.FormatElementList = OracleDateFormat.FormatElementList[:0]
OracleDateFormat.analysePattern(pattern)
}
}
func format(dt []int, pattern string, scale int32, language int) string {
f := getFormat()
f.setPattern(pattern)
f.language = language
f.scale = scale
ret := f.format(dt)
return ret
}
func (OracleDateFormat *oracleDateFormat) format(dt []int) string {
sf := strings.Builder{}
tzStart := false
for _, obj := range OracleDateFormat.FormatElementList {
_, ok1 := obj.(tzhElement)
_, ok2 := obj.(tzmElement)
if !tzStart && (ok1 || ok2) {
tzStart = true
if dt[OFFSET_TIMEZONE] < 0 {
sf.WriteString("-")
} else {
sf.WriteString("+")
}
}
if e, ok := obj.(element); ok {
sf.WriteString(e.format(dt))
} else {
sf.WriteString(obj.(string))
}
}
return sf.String()
}
/**
* 解析格式串
*/
func (OracleDateFormat *oracleDateFormat) analysePattern(pattern string) ([]interface{}, error) {
// 按分隔符split
pattern = strings.TrimSpace(pattern)
l := len(pattern)
var splitPatterns []string
starti := 0
var curChar rune
for i := 0; i < l; i++ {
curChar = rune(pattern[i])
if !unicode.IsDigit(curChar) && !unicode.IsLetter(curChar) {
if i > starti {
splitPatterns = append(splitPatterns, pattern[starti:i])
}
splitPatterns = append(splitPatterns, string(curChar))
starti = i + 1
} else if i == l-1 {
splitPatterns = append(splitPatterns, pattern[starti:i+1])
}
}
// 每个串按照从完整串,然后依次去掉一个末尾字符 来进行尝试规约
for _, subPattern := range splitPatterns {
if len(subPattern) != 1 || unicode.IsDigit(rune(subPattern[0])) || unicode.IsLetter(rune(subPattern[0])) {
fmtWord := subPattern
for subPattern != "" {
i := len(subPattern)
for ; i > 0; i-- {
fmtWord = subPattern[0:i]
element, err := OracleDateFormat.getFormatElement(fmtWord)
if err != nil {
return nil, err
}
if element != nil {
// 忽略时区前面的+-号
if element == OracleDateFormat.TZHElement || element == OracleDateFormat.TZMElement {
var lastFormatElement string = OracleDateFormat.FormatElementList[len(OracleDateFormat.FormatElementList)-1].(string)
if util.StringUtil.Equals("+", lastFormatElement) || util.StringUtil.Equals("-", lastFormatElement) {
OracleDateFormat.FormatElementList = OracleDateFormat.FormatElementList[:len(OracleDateFormat.FormatElementList)-2]
}
}
OracleDateFormat.FormatElementList = append(OracleDateFormat.FormatElementList, element)
if i == len(subPattern) {
subPattern = ""
} else {
subPattern = subPattern[i:len(subPattern)]
}
break
}
}
if i == 0 {
// 非标识符串
OracleDateFormat.FormatElementList = append(OracleDateFormat.FormatElementList, subPattern)
break
}
}
} else {
OracleDateFormat.FormatElementList = append(OracleDateFormat.FormatElementList, subPattern)
}
}
return OracleDateFormat.FormatElementList, nil
}
func (OracleDateFormat *oracleDateFormat) getFormatElement(word string) (element, error) {
if util.StringUtil.EqualsIgnoreCase("HH", word) || util.StringUtil.EqualsIgnoreCase("HH12", word) {
return OracleDateFormat.HH12Element, nil
} else if util.StringUtil.EqualsIgnoreCase("HH24", word) {
return OracleDateFormat.HH24Element, nil
} else if util.StringUtil.EqualsIgnoreCase("MI", word) {
return OracleDateFormat.MIElement, nil
} else if util.StringUtil.EqualsIgnoreCase("SS", word) {
return OracleDateFormat.SSElement, nil
} else if util.StringUtil.EqualsIgnoreCase("AM", word) || util.StringUtil.EqualsIgnoreCase("A.M.", word) || util.StringUtil.EqualsIgnoreCase("PM", word) || util.StringUtil.EqualsIgnoreCase("P.M.", word) {
return OracleDateFormat.AMElement, nil
} else if util.StringUtil.Equals("MONTH", word) {
OracleDateFormat.MonthElement.upperCase = true
OracleDateFormat.MonthElement.lowerCase = false
return OracleDateFormat.MonthElement, nil
} else if util.StringUtil.Equals("month", word) {
OracleDateFormat.MonthElement.upperCase = false
OracleDateFormat.MonthElement.lowerCase = true
return OracleDateFormat.MonthElement, nil
} else if util.StringUtil.EqualsIgnoreCase("Month", word) {
OracleDateFormat.MonthElement.upperCase = false
OracleDateFormat.MonthElement.lowerCase = false
return OracleDateFormat.MonthElement, nil
} else if util.StringUtil.Equals("MON", word) {
OracleDateFormat.MonElement.upperCase = true
OracleDateFormat.MonElement.lowerCase = false
return OracleDateFormat.MonElement, nil
} else if util.StringUtil.Equals("mon", word) {
OracleDateFormat.MonElement.upperCase = false
OracleDateFormat.MonElement.lowerCase = true
return OracleDateFormat.MonElement, nil
} else if util.StringUtil.EqualsIgnoreCase("Mon", word) {
OracleDateFormat.MonElement.upperCase = false
OracleDateFormat.MonElement.lowerCase = false
return OracleDateFormat.MonElement, nil
} else if util.StringUtil.EqualsIgnoreCase("MM", word) {
return OracleDateFormat.MMElement, nil
} else if util.StringUtil.EqualsIgnoreCase("DD", word) {
return OracleDateFormat.DDElement, nil
} else if util.StringUtil.EqualsIgnoreCase("TZH", word) {
return OracleDateFormat.TZHElement, nil
} else if util.StringUtil.EqualsIgnoreCase("TZM", word) {
return OracleDateFormat.TZMElement, nil
} else if strings.Index(word, "Y") == 0 || strings.Index(word, "y") == 0 {
OracleDateFormat.YearElement.len = len(word)
return OracleDateFormat.YearElement, nil
} else if strings.Index(word, "F") == 0 || strings.Index(word, "f") == 0 {
word = strings.ToUpper(word)
numIndex := strings.LastIndex(word, "F") + 1
var count int64
var err error
if numIndex < len(word) {
count, err = strconv.ParseInt(word[numIndex:len(word)], 10, 32)
if err != nil {
return nil, err
}
} else {
count = -1
}
OracleDateFormat.FElement.len = int(count)
return OracleDateFormat.FElement, nil
}
return nil, nil
}
+124
View File
@@ -0,0 +1,124 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"strconv"
"strings"
)
type Properties struct {
innerProps map[string]string
}
func NewProperties() *Properties {
p := Properties{
innerProps: make(map[string]string, 50),
}
return &p
}
func (g *Properties) SetProperties(p *Properties) {
if p == nil {
return
}
for k, v := range p.innerProps {
g.Set(strings.ToLower(k), v)
}
}
func (g *Properties) Len() int {
return len(g.innerProps)
}
func (g *Properties) IsNil() bool {
return g == nil || g.innerProps == nil
}
func (g *Properties) GetString(key, def string) string {
v, ok := g.innerProps[strings.ToLower(key)]
if !ok || v == "" {
return def
}
return v
}
func (g *Properties) GetInt(key string, def int, min int, max int) int {
value, ok := g.innerProps[strings.ToLower(key)]
if !ok || value == "" {
return def
}
i, err := strconv.Atoi(value)
if err != nil {
return def
}
if i > max || i < min {
return def
}
return i
}
func (g *Properties) GetBool(key string, def bool) bool {
value, ok := g.innerProps[strings.ToLower(key)]
if !ok || value == "" {
return def
}
b, err := strconv.ParseBool(value)
if err != nil {
return def
}
return b
}
func (g *Properties) GetTrimString(key string, def string) string {
value, ok := g.innerProps[strings.ToLower(key)]
if !ok || value == "" {
return def
} else {
return strings.TrimSpace(value)
}
}
func (g *Properties) GetStringArray(key string, def []string) []string {
value, ok := g.innerProps[strings.ToLower(key)]
if ok || value != "" {
array := strings.Split(value, ",")
if len(array) > 0 {
return array
}
}
return def
}
//func (g *Properties) GetBool(key string) bool {
// i, _ := strconv.ParseBool(g.innerProps[key])
// return i
//}
func (g *Properties) Set(key, value string) {
g.innerProps[strings.ToLower(key)] = value
}
func (g *Properties) SetIfNotExist(key, value string) {
if _, ok := g.innerProps[strings.ToLower(key)]; !ok {
g.Set(key, value)
}
}
// 如果p有g没有的键值对,添加进g中
func (g *Properties) SetDiffProperties(p *Properties) {
if p == nil {
return
}
for k, v := range p.innerProps {
if _, ok := g.innerProps[strings.ToLower(k)]; !ok {
g.innerProps[strings.ToLower(k)] = v
}
}
}
+246
View File
@@ -0,0 +1,246 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"math/rand"
"strconv"
"sync"
"time"
"gitee.com/chunanyong/dm/util"
)
var rwMap sync.Map
type rwCounter struct {
ntrx_primary int64
ntrx_total int64
primaryPercent float64
standbyPercent float64
standbyNTrxMapMu sync.RWMutex
standbyNTrxMap map[string]int64
standbyIdMapMu sync.RWMutex
standbyIdMap map[string]int32
standbyCount int32
flag []int32
increments []int32
//用来计数,选择存活的standby节点
indexCount int64
}
func newRWCounter(primaryPercent int32, standbyCount int32) *rwCounter {
rwc := new(rwCounter)
rwc.standbyNTrxMap = make(map[string]int64)
rwc.standbyIdMap = make(map[string]int32)
rwc.reset(primaryPercent, standbyCount)
return rwc
}
func (rwc *rwCounter) reset(primaryPercent int32, standbyCount int32) {
rwc.ntrx_primary = 0
rwc.ntrx_total = 0
rwc.standbyCount = standbyCount
rwc.increments = make([]int32, standbyCount+1)
rwc.flag = make([]int32, standbyCount+1)
var gcd = util.GCD(primaryPercent*standbyCount, 100-primaryPercent)
rwc.increments[0] = primaryPercent * standbyCount / gcd
for i, tmp := 1, (100-primaryPercent)/gcd; i < len(rwc.increments); i++ {
rwc.increments[i] = tmp
}
copy(rwc.flag, rwc.increments)
if standbyCount > 0 {
rwc.primaryPercent = float64(primaryPercent) / 100.0
rwc.standbyPercent = float64(100-primaryPercent) / 100.0 / float64(standbyCount)
} else {
rwc.primaryPercent = 1
rwc.standbyPercent = 0
}
}
// 连接创建成功后调用,需要服务器返回standbyCount
func getRwCounterInstance(conn *DmConnection, standbyCount int32) *rwCounter {
key := conn.dmConnector.host + "_" + strconv.Itoa(int(conn.dmConnector.port)) + "_" + strconv.Itoa(int(conn.dmConnector.rwPercent))
val, ok := rwMap.Load(key)
if !ok {
rwc := newRWCounter(conn.dmConnector.rwPercent, standbyCount)
rwMap.Store(key, rwc)
return rwc
} else {
rwc := val.(*rwCounter)
if rwc.standbyCount != standbyCount {
rwc.reset(conn.dmConnector.rwPercent, standbyCount)
}
return rwc
}
}
/**
* @return 主机;
*/
func (rwc *rwCounter) countPrimary() RWSiteEnum {
rwc.adjustNtrx()
rwc.increasePrimaryNtrx()
return PRIMARY
}
/**
* @param dest 主机; 备机; any;
* @return 主机; 备机
*/
func (rwc *rwCounter) count(dest RWSiteEnum, standby *DmConnection) RWSiteEnum {
rwc.adjustNtrx()
switch dest {
case ANYSITE:
{
if rwc.primaryPercent == 1 || (rwc.flag[0] > rwc.getStandbyFlag(standby) && rwc.flag[0] > util.Sum(rwc.flag[1:])) {
rwc.increasePrimaryNtrx()
dest = PRIMARY
} else {
rwc.increaseStandbyNtrx(standby)
dest = STANDBY
}
}
case STANDBY:
{
rwc.increaseStandbyNtrx(standby)
}
case PRIMARY:
{
rwc.increasePrimaryNtrx()
}
}
return dest
}
/**
* 防止ntrx超出有效范围,等比调整
*/
func (rwc *rwCounter) adjustNtrx() {
if rwc.ntrx_total >= INT64_MAX {
var min int64
var i = 0
func() {
rwc.standbyNTrxMapMu.Lock()
defer rwc.standbyNTrxMapMu.Unlock()
for _, num := range rwc.standbyNTrxMap {
if i == 0 || num < min {
min = num
}
i++
}
if rwc.ntrx_primary < min {
min = rwc.ntrx_primary
}
rwc.ntrx_primary /= min
rwc.ntrx_total /= min
for k, v := range rwc.standbyNTrxMap {
rwc.standbyNTrxMap[k] = v / min
}
}()
}
if rwc.flag[0] <= 0 && util.Sum(rwc.flag[1:]) <= 0 {
// 如果主库事务数以及所有备库事务数的总和 都 <= 0, 重置事务计数,给每个库的事务计数加上初始计数值
for i := 0; i < len(rwc.flag); i++ {
rwc.flag[i] += rwc.increments[i]
}
}
}
func (rwc *rwCounter) increasePrimaryNtrx() {
rwc.ntrx_primary++
rwc.flag[0]--
rwc.ntrx_total++
}
//func (rwc *rwCounter) getStandbyNtrx(standby *DmConnection) int64 {
// key := standby.dmConnector.host + ":" + strconv.Itoa(int(standby.dmConnector.port))
// ret, ok := rwc.standbyNTrxMap[key]
// if !ok {
// ret = 0
// }
//
// return ret
//}
func (rwc *rwCounter) getStandbyId(standby *DmConnection) int32 {
key := standby.dmConnector.host + ":" + strconv.Itoa(int(standby.dmConnector.port))
rwc.standbyIdMapMu.Lock()
defer rwc.standbyIdMapMu.Unlock()
sid, ok := rwc.standbyIdMap[key]
if !ok {
sid = int32(len(rwc.standbyIdMap) + 1) // 下标0是primary
if sid > rwc.standbyCount {
// 不在有效备库中
return -1
}
rwc.standbyIdMap[key] = sid
}
return sid
}
func (rwc *rwCounter) getStandbyFlag(standby *DmConnection) int32 {
sid := rwc.getStandbyId(standby)
if sid > 0 && sid < int32(len(rwc.flag)) {
// 保证备库有效
return rwc.flag[sid]
}
return 0
}
func (rwc *rwCounter) increaseStandbyNtrx(standby *DmConnection) {
key := standby.dmConnector.host + ":" + strconv.Itoa(int(standby.dmConnector.port))
func() {
rwc.standbyNTrxMapMu.Lock()
defer rwc.standbyNTrxMapMu.Unlock()
ret, ok := rwc.standbyNTrxMap[key]
if ok {
ret += 1
} else {
ret = 1
}
rwc.standbyNTrxMap[key] = ret
}()
func() {
rwc.standbyIdMapMu.Lock()
defer rwc.standbyIdMapMu.Unlock()
sid, ok := rwc.standbyIdMap[key]
if !ok {
sid = int32(len(rwc.standbyIdMap) + 1) // 下标0是primary
rwc.standbyIdMap[key] = sid
}
rwc.flag[sid]--
}()
rwc.ntrx_total++
}
func (rwc *rwCounter) random(rowCount int32) int32 {
rand.Seed(time.Now().UnixNano())
if rowCount > rwc.standbyCount {
return rand.Int31n(rwc.standbyCount)
} else {
return rand.Int31n(rowCount)
}
}
func (rwc *rwCounter) String() string {
return "PERCENT(P/S) : " + strconv.FormatFloat(rwc.primaryPercent, 'f', -1, 64) + "/" + strconv.FormatFloat(rwc.standbyPercent, 'f', -1, 64) + "\nNTRX_PRIMARY : " +
strconv.FormatInt(rwc.ntrx_primary, 10) + "\nNTRX_TOTAL : " + strconv.FormatInt(rwc.ntrx_total, 10) + "\nNTRX_STANDBY : "
}
+554
View File
@@ -0,0 +1,554 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"context"
"database/sql"
"database/sql/driver"
"errors"
"io"
"regexp"
"strings"
"time"
"gitee.com/chunanyong/dm/util"
)
const (
SQL_SELECT_STANDBY = "select distinct mailIni.inst_name, mailIni.INST_IP, mailIni.INST_PORT, archIni.arch_status " +
"from v$arch_status archIni " +
"left join (select * from V$DM_MAL_INI) mailIni on archIni.arch_dest = mailIni.inst_name " +
"left join V$MAL_LINK_STATUS on CTL_LINK_STATUS = 'CONNECTED' AND DATA_LINK_STATUS = 'CONNECTED' " +
"where archIni.arch_type in ('TIMELY', 'REALTIME') AND archIni.arch_status = 'VALID'"
SQL_SELECT_STANDBY2 = "select distinct " +
"mailIni.mal_inst_name, mailIni.mal_INST_HOST, mailIni.mal_INST_PORT, archIni.arch_status " +
"from v$arch_status archIni " + "left join (select * from V$DM_MAL_INI) mailIni " +
"on archIni.arch_dest = mailIni.mal_inst_name " + "left join V$MAL_LINK_STATUS " +
"on CTL_LINK_STATUS = 'CONNECTED' AND DATA_LINK_STATUS = 'CONNECTED' " +
"where archIni.arch_type in ('TIMELY', 'REALTIME') AND archIni.arch_status = 'VALID'"
)
type rwUtil struct {
}
var RWUtil = rwUtil{}
func (RWUtil rwUtil) connect(c *DmConnector, ctx context.Context) (*DmConnection, error) {
c.loginMode = LOGIN_MODE_PRIMARY_ONLY
connection, err := c.connect(ctx)
if err != nil {
return nil, err
}
connection.rwInfo.rwCounter = getRwCounterInstance(connection, connection.StandbyCount)
err = RWUtil.connectStandby(connection)
return connection, err
}
func (RWUtil rwUtil) reconnect(connection *DmConnection) error {
if connection.rwInfo == nil {
return nil
}
RWUtil.removeStandby(connection)
err := connection.reconnect()
if err != nil {
return err
}
connection.rwInfo.cleanup()
connection.rwInfo.rwCounter = getRwCounterInstance(connection, connection.StandbyCount)
err = RWUtil.connectStandby(connection)
return err
}
func (RWUtil rwUtil) recoverStandby(connection *DmConnection) error {
if connection.closed.IsSet() || RWUtil.isStandbyAlive(connection) {
return nil
}
ts := time.Now().UnixNano() / 1000000
freq := int64(connection.dmConnector.rwStandbyRecoverTime)
if freq <= 0 || ts-connection.rwInfo.tryRecoverTs < freq {
return nil
}
err := RWUtil.connectStandby(connection)
if err == nil && !RWUtil.checkStatusValid(connection) {
RWUtil.removeStandby(connection)
}
connection.rwInfo.tryRecoverTs = ts
return err
}
func (RWUtil rwUtil) checkStatusValid(connection *DmConnection) bool {
standbyConn := connection.rwInfo.connStandby
if standbyConn == nil {
return false
}
var id int32 = -1
stmt, rs, err := connection.driverQuery("select oguid from v$instance")
defer stmt.close()
defer rs.close()
if err == nil {
dest := make([]driver.Value, 1)
err := rs.next(dest)
if err == nil {
id = dest[0].(int32)
} else {
return false
}
} else {
return false
}
stmt2, rs2, err2 := standbyConn.driverQuery("select oguid from v$instance")
defer stmt2.close()
defer rs2.close()
if err2 == nil {
dest2 := make([]driver.Value, 1)
err2 := rs.next(dest2)
if err2 == nil {
if dest2[0].(int32) == id {
return true
}
}
}
return false
}
func (RWUtil rwUtil) connectStandby(connection *DmConnection) error {
var err error
db, err := RWUtil.chooseValidStandby(connection)
if err != nil {
return err
}
if db == nil {
return nil
}
standbyConnectorValue := *connection.dmConnector
standbyConnector := &standbyConnectorValue
standbyConnector.host = db.host
standbyConnector.port = db.port
standbyConnector.rwStandby = true
standbyConnector.group = nil
standbyConnector.loginMode = LOGIN_MODE_STANDBY_ONLY
standbyConnector.switchTimes = 0
connection.rwInfo.connStandby, err = standbyConnector.connectSingle(context.Background())
if err != nil {
return err
}
if connection.rwInfo.connStandby.SvrMode != SERVER_MODE_STANDBY || connection.rwInfo.connStandby.SvrStat != SERVER_STATUS_OPEN {
RWUtil.removeStandby(connection)
}
return nil
}
func (RWUtil rwUtil) chooseValidStandby(connection *DmConnection) (*ep, error) {
var filter, filter2 string
var stmt *DmStatement
var rs *DmRows
var err error
if connection.dmConnector.rwSeparate == RW_SEPARATE_USER_DEFINED {
return RWUtil.chooseStandbyUserDefined(connection), nil
} else if connection.dmConnector.rwSeparate == RW_SEPARATE_DB_APPLY_WAIT {
return newEP(connection.StandbyHost, connection.StandbyPort), nil
} else if connection.dmConnector.rwSeparate == RW_SEPARATE_EP_GROUP {
epStr := ""
if connection.dmConnector.group != nil {
for i := 0; i < len(connection.dmConnector.group.epList); i++ {
if i != 0 {
epStr += ","
}
epStr += "'" + connection.dmConnector.group.epList[i].host + ":" + string(connection.dmConnector.group.epList[i].port) + "'"
}
}
if len(epStr) > 0 {
filter = " and (mailIni.INST_IP || ':'|| mailIni.INST_PORT) in (" + epStr + ")"
filter2 = " and (mailIni.mal_INST_HOST || ':'|| mailIni.mal_INST_PORT) in (" + epStr + ")"
}
}
if connection.Malini2 {
stmt, rs, err = connection.driverQuery(SQL_SELECT_STANDBY2 + filter2)
} else {
stmt, rs, err = connection.driverQuery(SQL_SELECT_STANDBY + filter)
}
defer func() {
if rs != nil {
rs.close()
}
if stmt != nil {
stmt.close()
}
}()
if err != nil {
rs.close()
stmt.close()
if connection.Malini2 {
stmt, rs, err = connection.driverQuery(SQL_SELECT_STANDBY2 + filter)
} else {
stmt, rs, err = connection.driverQuery(SQL_SELECT_STANDBY + filter2)
}
}
if err == nil {
count := int32(rs.CurrentRows.getRowCount())
if count > 0 {
connection.rwInfo.rwCounter = getRwCounterInstance(connection, count)
i := int32(0)
rowIndex := connection.rwInfo.rwCounter.random(count)
dest := make([]driver.Value, 3)
for err := rs.next(dest); err != io.EOF; err = rs.next(dest) {
if i == rowIndex {
ep := newEP(dest[1].(string), dest[2].(int32))
return ep, nil
}
i++
}
}
}
if err != nil {
return nil, errors.New("choose valid standby error!" + err.Error())
}
return nil, nil
}
func (RWUtil rwUtil) chooseStandbyUserDefined(connection *DmConnection) *ep {
epGroup := connection.dmConnector.group.epList
if epGroup == nil {
return nil
}
aliveEp := make([]*ep, len(epGroup))
aliveCount := 0
for i := 0; i < len(epGroup); i++ {
ep := epGroup[i]
if isAliveStandby(ep, connection) {
aliveEp = append(aliveEp, epGroup[i])
aliveCount++
}
}
if aliveCount > 0 {
if connection.rwInfo.rwCounter.indexCount == INT64_MAX {
connection.rwInfo.rwCounter.indexCount = 0
}
ret := aliveEp[int(connection.rwInfo.rwCounter.indexCount)%aliveCount]
connection.rwInfo.rwCounter.indexCount++
return ret
}
return nil
}
func isAliveStandby(ep *ep, connection *DmConnection) bool {
standbyConnectorValue := *connection.dmConnector
standbyConnector := &standbyConnectorValue
standbyConnector.host = ep.host
standbyConnector.port = ep.port
standbyConnector.rwStandby = true
standbyConnector.group = nil
standbyConnector.loginMode = LOGIN_MODE_STANDBY_ONLY
standbyConnector.switchTimes = 0
standbyConnect, err := standbyConnector.connectSingle(context.Background())
if err != nil {
return false
}
defer standbyConnect.close()
if standbyConnect.SvrMode != SERVER_MODE_STANDBY || standbyConnect.SvrStat != SERVER_STATUS_OPEN {
return false
}
return true
}
func (RWUtil rwUtil) afterExceptionOnStandby(connection *DmConnection, e error) {
if e.(*DmError).ErrCode == ECGO_COMMUNITION_ERROR.ErrCode {
RWUtil.removeStandby(connection)
}
}
func (RWUtil rwUtil) removeStandby(connection *DmConnection) {
if connection.rwInfo.connStandby != nil {
connection.rwInfo.connStandby.close()
connection.rwInfo.connStandby = nil
}
}
func (RWUtil rwUtil) isCreateStandbyStmt(stmt *DmStatement) bool {
return stmt != nil && stmt.rwInfo.readOnly && RWUtil.isStandbyAlive(stmt.dmConn)
}
func (RWUtil rwUtil) executeByConn(conn *DmConnection, query string, execute1 func() (interface{}, error), execute2 func(otherConn *DmConnection) (interface{}, error)) (interface{}, error) {
if err := RWUtil.recoverStandby(conn); err != nil {
return nil, err
}
RWUtil.distributeSqlByConn(conn, query)
turnToPrimary := false
ret, err := execute1()
if err != nil {
if conn.rwInfo.connCurrent == conn.rwInfo.connStandby {
RWUtil.afterExceptionOnStandby(conn, err)
turnToPrimary = true
} else {
return nil, err
}
}
curConn := conn.rwInfo.connCurrent
var otherConn *DmConnection
if curConn != conn {
otherConn = conn
} else {
otherConn = conn.rwInfo.connStandby
}
switch curConn.lastExecInfo.retSqlType {
case Dm_build_794, Dm_build_795, Dm_build_799, Dm_build_806, Dm_build_805, Dm_build_797:
{
if otherConn != nil {
execute2(otherConn)
}
}
case Dm_build_804:
{
sqlhead := regexp.MustCompile("[ (]").Split(strings.TrimSpace(query), 2)[0]
if util.StringUtil.EqualsIgnoreCase(sqlhead, "SP_SET_PARA_VALUE") || util.StringUtil.EqualsIgnoreCase(sqlhead, "SP_SET_SESSION_READONLY") {
if otherConn != nil {
execute2(otherConn)
}
}
}
case Dm_build_803:
{
if conn.dmConnector.rwHA && curConn == conn.rwInfo.connStandby &&
(curConn.lastExecInfo.rsDatas == nil || len(curConn.lastExecInfo.rsDatas) == 0) {
turnToPrimary = true
}
}
}
if turnToPrimary {
conn.rwInfo.toPrimary()
conn.rwInfo.connCurrent = conn
return execute2(conn)
}
return ret, nil
}
func (RWUtil rwUtil) executeByStmt(stmt *DmStatement, execute1 func() (interface{}, error), execute2 func(otherStmt *DmStatement) (interface{}, error)) (interface{}, error) {
orgStmt := stmt.rwInfo.stmtCurrent
query := stmt.nativeSql
if err := RWUtil.recoverStandby(stmt.dmConn); err != nil {
return nil, err
}
RWUtil.distributeSqlByStmt(stmt)
if orgStmt != stmt.rwInfo.stmtCurrent {
RWUtil.copyStatement(orgStmt, stmt.rwInfo.stmtCurrent)
stmt.rwInfo.stmtCurrent.nativeSql = orgStmt.nativeSql
}
turnToPrimary := false
ret, err := execute1()
if err != nil {
if stmt.rwInfo.stmtCurrent == stmt.rwInfo.stmtStandby {
RWUtil.afterExceptionOnStandby(stmt.dmConn, err)
turnToPrimary = true
} else {
return nil, err
}
}
curStmt := stmt.rwInfo.stmtCurrent
var otherStmt *DmStatement
if curStmt != stmt {
otherStmt = stmt
} else {
otherStmt = stmt.rwInfo.stmtStandby
}
switch curStmt.execInfo.retSqlType {
case Dm_build_794, Dm_build_795, Dm_build_799, Dm_build_806, Dm_build_805, Dm_build_797:
{
if otherStmt != nil {
RWUtil.copyStatement(curStmt, otherStmt)
execute2(otherStmt)
}
}
case Dm_build_804:
{
var tmpsql string
if query != "" {
tmpsql = strings.TrimSpace(query)
} else if stmt.nativeSql != "" {
tmpsql = strings.TrimSpace(stmt.nativeSql)
} else {
tmpsql = ""
}
sqlhead := regexp.MustCompile("[ (]").Split(tmpsql, 2)[0]
if util.StringUtil.EqualsIgnoreCase(sqlhead, "SP_SET_PARA_VALUE") || util.StringUtil.EqualsIgnoreCase(sqlhead, "SP_SET_SESSION_READONLY") {
if otherStmt != nil {
RWUtil.copyStatement(curStmt, otherStmt)
execute2(otherStmt)
}
}
}
case Dm_build_803:
{
if stmt.dmConn.dmConnector.rwHA && curStmt == stmt.rwInfo.stmtStandby &&
(curStmt.execInfo.rsDatas == nil || len(curStmt.execInfo.rsDatas) == 0) {
turnToPrimary = true
}
}
}
if turnToPrimary {
stmt.dmConn.rwInfo.toPrimary()
stmt.rwInfo.stmtCurrent = stmt
RWUtil.copyStatement(stmt.rwInfo.stmtStandby, stmt)
return execute2(stmt)
}
return ret, nil
}
func (RWUtil rwUtil) checkReadonlyByConn(conn *DmConnection, sql string) bool {
readonly := true
if sql != "" && !conn.dmConnector.rwIgnoreSql {
tmpsql := strings.TrimSpace(sql)
sqlhead := strings.SplitN(tmpsql, " ", 2)[0]
if util.StringUtil.EqualsIgnoreCase(sqlhead, "INSERT") ||
util.StringUtil.EqualsIgnoreCase(sqlhead, "UPDATE") ||
util.StringUtil.EqualsIgnoreCase(sqlhead, "DELETE") ||
util.StringUtil.EqualsIgnoreCase(sqlhead, "CREATE") ||
util.StringUtil.EqualsIgnoreCase(sqlhead, "TRUNCATE") ||
util.StringUtil.EqualsIgnoreCase(sqlhead, "DROP") ||
util.StringUtil.EqualsIgnoreCase(sqlhead, "ALTER") {
readonly = false
} else {
readonly = true
}
}
return readonly
}
func (RWUtil rwUtil) checkReadonlyByStmt(stmt *DmStatement) bool {
return RWUtil.checkReadonlyByConn(stmt.dmConn, stmt.nativeSql)
}
func (RWUtil rwUtil) distributeSqlByConn(conn *DmConnection, query string) RWSiteEnum {
var dest RWSiteEnum
if !RWUtil.isStandbyAlive(conn) {
dest = conn.rwInfo.toPrimary()
} else if !RWUtil.checkReadonlyByConn(conn, query) {
dest = conn.rwInfo.toPrimary()
} else if (conn.rwInfo.distribute == PRIMARY && !conn.trxFinish) ||
(conn.rwInfo.distribute == STANDBY && !conn.rwInfo.connStandby.trxFinish) {
dest = conn.rwInfo.distribute
} else if conn.IsoLevel != int32(sql.LevelSerializable) {
dest = conn.rwInfo.toAny()
} else {
dest = conn.rwInfo.toPrimary()
}
if dest == PRIMARY {
conn.rwInfo.connCurrent = conn
} else {
conn.rwInfo.connCurrent = conn.rwInfo.connStandby
}
return dest
}
func (RWUtil rwUtil) distributeSqlByStmt(stmt *DmStatement) RWSiteEnum {
var dest RWSiteEnum
if !RWUtil.isStandbyAlive(stmt.dmConn) {
dest = stmt.dmConn.rwInfo.toPrimary()
} else if !RWUtil.checkReadonlyByStmt(stmt) {
dest = stmt.dmConn.rwInfo.toPrimary()
} else if (stmt.dmConn.rwInfo.distribute == PRIMARY && !stmt.dmConn.trxFinish) ||
(stmt.dmConn.rwInfo.distribute == STANDBY && !stmt.dmConn.rwInfo.connStandby.trxFinish) {
dest = stmt.dmConn.rwInfo.distribute
} else if stmt.dmConn.IsoLevel != int32(sql.LevelSerializable) {
dest = stmt.dmConn.rwInfo.toAny()
} else {
dest = stmt.dmConn.rwInfo.toPrimary()
}
if dest == STANDBY && !RWUtil.isStandbyStatementValid(stmt) {
var err error
stmt.rwInfo.stmtStandby, err = stmt.dmConn.rwInfo.connStandby.prepare(stmt.nativeSql)
if err != nil {
dest = stmt.dmConn.rwInfo.toPrimary()
}
}
if dest == PRIMARY {
stmt.rwInfo.stmtCurrent = stmt
} else {
stmt.rwInfo.stmtCurrent = stmt.rwInfo.stmtStandby
}
return dest
}
func (RWUtil rwUtil) isStandbyAlive(connection *DmConnection) bool {
return connection.rwInfo.connStandby != nil && !connection.rwInfo.connStandby.closed.IsSet()
}
func (RWUtil rwUtil) isStandbyStatementValid(statement *DmStatement) bool {
return statement.rwInfo.stmtStandby != nil && !statement.rwInfo.stmtStandby.closed
}
func (RWUtil rwUtil) copyStatement(srcStmt *DmStatement, destStmt *DmStatement) {
destStmt.nativeSql = srcStmt.nativeSql
destStmt.serverParams = srcStmt.serverParams
destStmt.bindParams = srcStmt.bindParams
destStmt.paramCount = srcStmt.paramCount
}
+108
View File
@@ -0,0 +1,108 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"database/sql"
"database/sql/driver"
)
var SQLName sqlName
type sqlName struct {
m_name string // 描述对象自身名称,
// 若为内置类型,则表示数据库端定义的名称,与dType相对应
m_pkgName string // 所在包的名称,适用于包中类型的定义
m_schName string // 描述对象所在模式名
m_fulName string // 描述对象完全限定名, 记录用户发送的名称信息;
// 以及接受服务器响应后,拼成的名称信息
m_schId int // 保存模式id,模式名无法传出,利用模式id查找
m_packId int // 保存包的id,包名无法传出,用于查找包名
m_conn *DmConnection
}
func (SqlName *sqlName) init() {
SqlName.m_name = ""
SqlName.m_pkgName = ""
SqlName.m_schName = ""
SqlName.m_fulName = ""
SqlName.m_schId = -1
SqlName.m_packId = -1
SqlName.m_conn = nil
}
func newSqlNameByFulName(fulName string) *sqlName {
o := new(sqlName)
o.init()
o.m_fulName = fulName
return o
}
func newSqlNameByConn(conn *DmConnection) *sqlName {
o := new(sqlName)
o.init()
o.m_conn = conn
return o
}
func (SqlName *sqlName) getFulName() (string, error) {
// 说明非内嵌式数据类型名称描述信息传入或已经获取过描述信息
if len(SqlName.m_fulName) > 0 {
return SqlName.m_fulName, nil
}
// 内嵌式数据类型无名称描述信息返回,直接返回null
if SqlName.m_name == "" {
// DBError.throwUnsupportedSQLException();
return "", nil
}
// 其他数据名描述信息
if SqlName.m_packId != 0 || SqlName.m_schId != 0 {
query := "SELECT NAME INTO ? FROM SYS.SYSOBJECTS WHERE ID=?"
params := make([]driver.Value, 2)
var v string
params[0] = sql.Out{Dest: &v}
if SqlName.m_packId != 0 {
params[1] = SqlName.m_packId
} else {
params[1] = SqlName.m_schId
}
rs, err := SqlName.m_conn.query(query, params)
if err != nil {
return "", err
}
rs.close()
// 说明是包中定义的对象
if SqlName.m_packId != 0 {
// pkg全名
SqlName.m_pkgName = v
SqlName.m_fulName = SqlName.m_pkgName + "." + SqlName.m_name
} else {
// 非包中定义的对象
// schema 名称
SqlName.m_schName = v
SqlName.m_fulName = SqlName.m_schName + "." + SqlName.m_name
}
}
// 将有效值返回
if len(SqlName.m_fulName) > 0 {
return SqlName.m_fulName, nil
} else {
return SqlName.m_name, nil
}
}
+324
View File
@@ -0,0 +1,324 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"bytes"
"strconv"
"strings"
"gitee.com/chunanyong/dm/parser"
"gitee.com/chunanyong/dm/util"
)
func (dc *DmConnection) lex(sql string) ([]*parser.LVal, error) {
if dc.lexer == nil {
dc.lexer = parser.NewLexer(strings.NewReader(sql), false)
} else {
dc.lexer.Reset(strings.NewReader(sql))
}
lexer := dc.lexer
var lval *parser.LVal
var err error
lvalList := make([]*parser.LVal, 0, 64)
lval, err = lexer.Yylex()
if err != nil {
return nil, err
}
for lval != nil {
lvalList = append(lvalList, lval)
lval.Position = len(lvalList)
lval, err = lexer.Yylex()
if err != nil {
return nil, err
}
}
return lvalList, nil
}
func lexSkipWhitespace(sql string, n int) ([]*parser.LVal, error) {
lexer := parser.NewLexer(strings.NewReader(sql), false)
var lval *parser.LVal
var err error
lvalList := make([]*parser.LVal, 0, 64)
lval, err = lexer.Yylex()
if err != nil {
return nil, err
}
for lval != nil && n > 0 {
lval.Position = len(lvalList)
if lval.Tp == parser.WHITESPACE_OR_COMMENT {
continue
}
lvalList = append(lvalList, lval)
n--
lval, err = lexer.Yylex()
if err != nil {
return nil, err
}
}
return lvalList, nil
}
func (dc *DmConnection) escape(sql string, keywords []string) (string, error) {
if (keywords == nil || len(keywords) == 0) && strings.Index(sql, "{") == -1 {
return sql, nil
}
var keywordMap map[string]interface{}
if keywords != nil && len(keywords) > 0 {
keywordMap = make(map[string]interface{}, len(keywords))
for _, keyword := range keywords {
keywordMap[strings.ToUpper(keyword)] = nil
}
}
nsql := bytes.NewBufferString("")
stack := make([]bool, 0, 64)
lvalList, err := dc.lex(sql)
if err != nil {
return "", err
}
for i := 0; i < len(lvalList); i++ {
lval0 := lvalList[i]
if lval0.Tp == parser.NORMAL {
if lval0.Value == "{" {
lval1 := next(lvalList, i+1)
if lval1 == nil || lval1.Tp != parser.NORMAL {
stack = append(stack, false)
nsql.WriteString(lval0.Value)
} else if util.StringUtil.EqualsIgnoreCase(lval1.Value, "escape") || util.StringUtil.EqualsIgnoreCase(lval1.Value, "call") {
stack = append(stack, true)
} else if util.StringUtil.EqualsIgnoreCase(lval1.Value, "oj") {
stack = append(stack, true)
lval1.Value = ""
lval1.Tp = parser.WHITESPACE_OR_COMMENT
} else if util.StringUtil.EqualsIgnoreCase(lval1.Value, "d") {
stack = append(stack, true)
lval1.Value = "date"
} else if util.StringUtil.EqualsIgnoreCase(lval1.Value, "t") {
stack = append(stack, true)
lval1.Value = "time"
} else if util.StringUtil.EqualsIgnoreCase(lval1.Value, "ts") {
stack = append(stack, true)
lval1.Value = "datetime"
} else if util.StringUtil.EqualsIgnoreCase(lval1.Value, "fn") {
stack = append(stack, true)
lval1.Value = ""
lval1.Tp = parser.WHITESPACE_OR_COMMENT
lval2 := next(lvalList, lval1.Position+1)
if lval2 != nil && lval2.Tp == parser.NORMAL && util.StringUtil.EqualsIgnoreCase(lval2.Value, "database") {
lval2.Value = "cur_database"
}
} else if util.StringUtil.Equals(lval1.Value, "?") {
lval2 := next(lvalList, lval1.Position+1)
if lval2 != nil && lval2.Tp == parser.NORMAL && util.StringUtil.EqualsIgnoreCase(lval2.Value, "=") {
lval3 := next(lvalList, lval2.Position+1)
if lval3 != nil && lval3.Tp == parser.NORMAL && util.StringUtil.EqualsIgnoreCase(lval3.Value, "call") {
stack = append(stack, true)
lval3.Value = ""
lval3.Tp = parser.WHITESPACE_OR_COMMENT
} else {
stack = append(stack, false)
nsql.WriteString(lval0.Value)
}
} else {
stack = append(stack, false)
nsql.WriteString(lval0.Value)
}
} else {
stack = append(stack, false)
nsql.WriteString(lval0.Value)
}
} else if util.StringUtil.Equals(lval0.Value, "}") {
if len(stack) != 0 && stack[len(stack)-1] {
} else {
nsql.WriteString(lval0.Value)
}
stack = stack[:len(stack)-1]
} else {
if keywordMap != nil {
_, ok := keywordMap[strings.ToUpper(lval0.Value)]
if ok {
nsql.WriteString("\"" + util.StringUtil.ProcessDoubleQuoteOfName(strings.ToUpper(lval0.Value)) + "\"")
} else {
nsql.WriteString(lval0.Value)
}
} else {
nsql.WriteString(lval0.Value)
}
}
} else if lval0.Tp == parser.STRING {
nsql.WriteString("'" + util.StringUtil.ProcessSingleQuoteOfName(lval0.Value) + "'")
} else {
nsql.WriteString(lval0.Value)
}
}
return nsql.String(), nil
}
func next(lvalList []*parser.LVal, start int) *parser.LVal {
var lval *parser.LVal
size := len(lvalList)
for i := start; i < size; i++ {
lval = lvalList[i]
if lval.Tp != parser.WHITESPACE_OR_COMMENT {
break
}
}
return lval
}
func (dc *DmConnection) execOpt(sql string, optParamList []OptParameter, serverEncoding string, backSlashFlag bool) (string, []OptParameter, error) {
nsql := bytes.NewBufferString("")
lvalList, err := dc.lex(sql)
if err != nil {
return sql, nil, err
}
if nil == lvalList || len(lvalList) == 0 {
return sql, nil, nil
}
firstWord := lvalList[0].Value
if !(util.StringUtil.EqualsIgnoreCase(firstWord, "INSERT") || util.StringUtil.EqualsIgnoreCase(firstWord, "SELECT") ||
util.StringUtil.EqualsIgnoreCase(firstWord, "UPDATE") || util.StringUtil.EqualsIgnoreCase(firstWord, "DELETE")) {
return sql, nil, nil
}
breakIndex := 0
for i := 0; i < len(lvalList); i++ {
lval := lvalList[i]
switch lval.Tp {
case parser.NULL:
{
nsql.WriteString("?")
optParamList = append(optParamList, newOptParameter(nil, NULL, NULL_PREC))
}
case parser.INT:
{
nsql.WriteString("?")
value, err := strconv.Atoi(lval.Value)
if err != nil {
return sql, nil, err
}
if value <= int(INT32_MAX) && value >= int(INT32_MIN) {
optParamList = append(optParamList, newOptParameter(G2DB.toInt32(int32(value)), INT, INT_PREC))
} else {
optParamList = append(optParamList, newOptParameter(G2DB.toInt64(int64(value)), BIGINT, BIGINT_PREC))
}
}
case parser.DOUBLE:
{
nsql.WriteString("?")
f, err := strconv.ParseFloat(lval.Value, 64)
if err != nil {
return sql, nil, err
}
optParamList = append(optParamList, newOptParameter(G2DB.toFloat64(f), DOUBLE, DOUBLE_PREC))
}
case parser.DECIMAL:
{
nsql.WriteString("?")
bytes, err := G2DB.toDecimal(lval.Value)
if err != nil {
return sql, nil, err
}
optParamList = append(optParamList, newOptParameter(bytes, DECIMAL, 0))
}
case parser.STRING:
{
if len(lval.Value) > int(INT16_MAX) {
nsql.WriteString("'" + util.StringUtil.ProcessSingleQuoteOfName(lval.Value) + "'")
} else {
nsql.WriteString("?")
if backSlashFlag {
lval.Value = util.StringUtil.Translate(lval.Value)
}
optParamList = append(optParamList, newOptParameter(Dm_build_1346.Dm_build_1562(lval.Value, serverEncoding, dc), VARCHAR, VARCHAR_PREC))
}
}
case parser.HEX_INT:
nsql.WriteString(lval.Value)
default:
nsql.WriteString(lval.Value)
}
if breakIndex > 0 {
break
}
}
if breakIndex > 0 {
for i := breakIndex + 1; i < len(lvalList); i++ {
nsql.WriteString(lvalList[i].Value)
}
}
return nsql.String(), optParamList, nil
}
func (dc *DmConnection) hasConst(sql string) (bool, error) {
lvalList, err := dc.lex(sql)
if err != nil {
return false, err
}
if nil == lvalList || len(lvalList) == 0 {
return false, nil
}
for i := 0; i < len(lvalList); i++ {
switch lvalList[i].Tp {
case parser.NULL, parser.INT, parser.DOUBLE, parser.DECIMAL, parser.STRING, parser.HEX_INT:
return true, nil
}
}
return false, nil
}
type OptParameter struct {
bytes []byte
ioType byte
tp int
prec int
scale int
}
func newOptParameter(bytes []byte, tp int, prec int) OptParameter {
o := new(OptParameter)
o.bytes = bytes
o.tp = tp
o.prec = prec
return *o
}
func (parameter *OptParameter) String() string {
if parameter.bytes == nil {
return ""
}
return string(parameter.bytes)
}
+44
View File
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
type StructDescriptor struct {
m_typeDesc *TypeDescriptor
}
func newStructDescriptor(fulName string, conn *DmConnection) (*StructDescriptor, error) {
sd := new(StructDescriptor)
if fulName == "" {
return nil, ECGO_INVALID_COMPLEX_TYPE_NAME.throw()
}
sd.m_typeDesc = newTypeDescriptorWithFulName(fulName, conn)
err := sd.m_typeDesc.parseDescByName()
if err != nil {
return nil, err
}
return sd, nil
}
func newStructDescriptorByTypeDescriptor(desc *TypeDescriptor) *StructDescriptor {
sd := new(StructDescriptor)
sd.m_typeDesc = desc
return sd
}
func (sd *StructDescriptor) getSize() int {
return sd.m_typeDesc.m_size
}
func (sd *StructDescriptor) getObjId() int {
return sd.m_typeDesc.m_objId
}
func (sd *StructDescriptor) getItemsDesc() []TypeDescriptor {
return sd.m_typeDesc.m_fieldsObj
}
+478
View File
@@ -0,0 +1,478 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"bufio"
"io"
"os"
"runtime"
"strconv"
"strings"
"sync"
"gitee.com/chunanyong/dm/util"
)
var LogDirDef, _ = os.Getwd()
var StatDirDef, _ = os.Getwd()
const (
DEFAULT_PORT int32 = 5236
//log level
LOG_OFF int = 0
LOG_ERROR int = 1
LOG_WARN int = 2
LOG_SQL int = 3
LOG_INFO int = 4
LOG_DEBUG int = 5
LOG_ALL int = 9
//stat
STAT_SQL_REMOVE_LATEST int = 0
STAT_SQL_REMOVE_OLDEST int = 1
// 编码字符集
ENCODING_UTF8 string = "UTF-8"
ENCODING_EUCKR string = "EUC-KR"
ENCODING_GB18030 string = "GB18030"
ENCODING_BIG5 string = "BIG5"
DbAliveCheckFreqDef = 0
LocaleDef = LANGUAGE_CN
// log
LogLevelDef = LOG_OFF // 日志级别:off, error, warn, sql, info, all
LogFlushFreqDef = 10 // 日志刷盘时间s (>=0)
LogFlushQueueSizeDef = 100 //日志队列大小
LogBufferSizeDef = 32 * 1024 // 日志缓冲区大小 (>0)
// stat
StatEnableDef = false //
StatFlushFreqDef = 3 // 日志刷盘时间s (>=0)
StatSlowSqlCountDef = 100 // 慢sql top行数,(0-1000)
StatHighFreqSqlCountDef = 100 // 高频sql top行数, (0-1000)
StatSqlMaxCountDef = 100000 // sql 统计最大值(0-100000)
StatSqlRemoveModeDef = STAT_SQL_REMOVE_LATEST // 记录sql数超过最大值时,sql淘汰方式
ClobToBytesDef = false //Clob是否转换为bytes
)
var (
DbAliveCheckFreq = DbAliveCheckFreqDef
Locale = LocaleDef // 0:简体中文 1:英文 2:繁体中文
// log
LogLevel = LogLevelDef // 日志级别:off, error, warn, sql, info, all
LogDir = LogDirDef
LogFlushFreq = LogFlushFreqDef // 日志刷盘时间s (>=0)
LogFlushQueueSize = LogFlushQueueSizeDef
LogBufferSize = LogBufferSizeDef // 日志缓冲区大小 (>0)
// stat
StatEnable = StatEnableDef //
StatDir = StatDirDef // jdbc工作目录,所有生成的文件都在该目录下
StatFlushFreq = StatFlushFreqDef // 日志刷盘时间s (>=0)
StatSlowSqlCount = StatSlowSqlCountDef // 慢sql top行数,(0-1000)
StatHighFreqSqlCount = StatHighFreqSqlCountDef // 高频sql top行数, (0-1000)
StatSqlMaxCount = StatSqlMaxCountDef // sql 统计最大值(0-100000)
StatSqlRemoveMode = StatSqlRemoveModeDef // 记录sql数超过最大值时,sql淘汰方式
/*---------------------------------------------------------------*/
ServerGroupMap sync.Map
GlobalProperties = NewProperties()
)
// filePath: dm_svc.conf 文件路径
func load(filePath string) {
if filePath == "" {
// 如果设置了环境变量则环境变量优先
filePath = os.Getenv("DM_SVC_PATH")
if filePath == "" {
// 否则使用默认
switch runtime.GOOS {
case "windows":
filePath = os.Getenv("SystemRoot") + "\\system32\\dm_svc.conf"
case "linux":
filePath = "/etc/dm_svc.conf"
default:
return
}
}
}
// 如果设置了连接串上svcConfPath,则串上优先
file, err := os.Open(filePath)
defer file.Close()
if err != nil {
return
}
fileReader := bufio.NewReader(file)
// GlobalProperties = NewProperties()
var groupProps *Properties
var line string //dm_svc.conf读取到的一行
for line, err = fileReader.ReadString('\n'); line != "" && (err == nil || err == io.EOF); line, err = fileReader.ReadString('\n') {
// 去除#标记的注释
if notesIndex := strings.IndexByte(line, '#'); notesIndex != -1 {
line = line[:notesIndex]
}
// 去除前后多余的空格
line = strings.TrimSpace(line)
if line == "" {
continue
}
if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
groupName := strings.ToLower(line[1 : len(line)-1])
dbGroup, ok := ServerGroupMap.Load(groupName)
if groupName == "" || !ok {
continue
}
groupProps = dbGroup.(*epGroup).props
if groupProps.IsNil() {
groupProps = NewProperties()
groupProps.SetProperties(GlobalProperties)
dbGroup.(*epGroup).props = groupProps
}
} else {
cfgInfo := [2]string{}
if index := strings.Index(line, "="); index > 0 {
cfgInfo[0] = line[0:index]
cfgInfo[1] = line[index+1:]
} else {
continue
}
key := strings.TrimSpace(cfgInfo[0])
value := strings.TrimSpace(cfgInfo[1])
if strings.HasPrefix(value, "(") && strings.HasSuffix(value, ")") {
value = strings.TrimSpace(value[1 : len(value)-1])
}
if key == "" || value == "" {
continue
}
// 区分属性是全局的还是组的
var success bool
if groupProps.IsNil() {
success = SetServerGroupProperties(GlobalProperties, key, value)
} else {
success = SetServerGroupProperties(groupProps, key, value)
}
if !success {
var serverGroup = parseServerName(key, value)
if serverGroup != nil {
serverGroup.props = NewProperties()
serverGroup.props.SetProperties(GlobalProperties)
ServerGroupMap.Store(strings.ToLower(key), serverGroup)
}
}
}
}
}
func SetServerGroupProperties(props *Properties, key string, value string) bool {
key = strings.ToUpper(key)
if key == "ADDRESS_REMAP" {
tmp := props.GetString(AddressRemapKey, "")
props.Set(AddressRemapKey, tmp+"("+value+")")
} else if key == "ALWAYS_ALLOW_COMMIT" {
props.Set(AlwayseAllowCommitKey, value)
} else if key == "APP_NAME" {
props.Set(AppNameKey, value)
} else if key == "AUTO_COMMIT" {
props.Set(AutoCommitKey, value)
} else if key == "BATCH_ALLOW_MAX_ERRORS" {
props.Set(BatchAllowMaxErrorsKey, value)
} else if key == "BATCH_CONTINUE_ON_ERROR" ||
key == "CONTINUE_BATCH_ON_ERROR" {
props.Set(ContinueBatchOnErrorKey, value)
} else if key == "BATCH_NOT_ON_CALL" {
props.Set(BatchNotOnCallKey, value)
} else if key == "BATCH_TYPE" {
props.Set(BatchTypeKey, value)
} else if key == "BUF_PREFETCH" {
props.Set(BufPrefetchKey, value)
} else if key == "CIPHER_PATH" {
props.Set(CipherPathKey, value)
} else if key == "CLUSTER" {
props.Set(ClusterKey, value)
} else if key == "COLUMN_NAME_UPPER_CASE" {
props.Set(ColumnNameUpperCaseKey, value)
} else if key == "COLUMN_NAME_CASE" {
props.Set(ColumnNameCaseKey, value)
} else if key == "COMPATIBLE_MODE" {
props.Set(CompatibleModeKey, value)
} else if key == "COMPRESS" ||
key == "COMPRESS_MSG" {
props.Set(CompressKey, value)
} else if key == "COMPRESS_ID" {
props.Set(CompressIdKey, value)
} else if key == "CONNECT_TIMEOUT" {
props.Set(ConnectTimeoutKey, value)
} else if key == "DO_SWITCH" ||
key == "AUTO_RECONNECT" {
props.Set(DoSwitchKey, value)
} else if key == "ENABLE_RS_CACHE" {
props.Set(EnRsCacheKey, value)
} else if key == "EP_SELECTION" {
props.Set(EpSelectorKey, value)
} else if key == "ESCAPE_PROCESS" {
props.Set(EscapeProcessKey, value)
} else if key == "IS_BDTA_RS" {
props.Set(IsBdtaRSKey, value)
} else if key == "KEY_WORDS" ||
key == "KEYWORDS" {
props.Set(KeywordsKey, value)
} else if key == "LANGUAGE" {
props.Set(LanguageKey, value)
} else if key == "LOB_MODE" {
props.Set(LobModeKey, value)
} else if key == "LOG_BUFFER_SIZE" {
props.Set(LogBufferSizeKey, value)
} else if key == "LOG_DIR" {
props.Set(LogDirKey, value)
} else if key == "LOG_FLUSH_FREQ" {
props.Set(LogFlushFreqKey, value)
} else if key == "LOG_FLUSHER_QUEUESIZE" {
props.Set(LogFlusherQueueSizeKey, value)
} else if key == "LOG_LEVEL" {
props.Set(LogLevelKey, value)
} else if key == "LOGIN_DSC_CTRL" {
props.Set(LoginDscCtrlKey, value)
} else if key == "LOGIN_ENCRYPT" {
props.Set(LoginEncryptKey, value)
} else if key == "LOGIN_MODE" {
props.Set(LoginModeKey, value)
} else if key == "LOGIN_STATUS" {
props.Set(LoginStatusKey, value)
} else if key == "MAX_ROWS" {
props.Set(MaxRowsKey, value)
} else if key == "MPP_LOCAL" {
props.Set(MppLocalKey, value)
} else if key == "OS_NAME" {
props.Set(OsNameKey, value)
} else if key == "RS_CACHE_SIZE" {
props.Set(RsCacheSizeKey, value)
} else if key == "RS_REFRESH_FREQ" {
props.Set(RsRefreshFreqKey, value)
} else if key == "RW_HA" {
props.Set(RwHAKey, value)
} else if key == "RW_IGNORE_SQL" {
props.Set(RwIgnoreSqlKey, value)
} else if key == "RW_PERCENT" {
props.Set(RwPercentKey, value)
} else if key == "RW_SEPARATE" {
props.Set(RwSeparateKey, value)
} else if key == "RW_STANDBY_RECOVER_TIME" {
props.Set(RwStandbyRecoverTimeKey, value)
} else if key == "SCHEMA" {
props.Set(SchemaKey, value)
} else if key == "CATALOG" {
props.Set(CatalogKey, value)
} else if key == "SESS_ENCODE" {
if IsSupportedCharset(value) {
props.Set("sessEncode", value)
}
} else if key == "SESSION_TIMEOUT" {
props.Set(SessionTimeoutKey, value)
} else if key == "SOCKET_TIMEOUT" {
props.Set(SocketTimeoutKey, value)
} else if key == "SSL_CERT_PATH" {
props.Set(SslCertPathKey, value)
} else if key == "SSL_FILES_PATH" {
props.Set(SslFilesPathKey, value)
} else if key == "SSL_KEY_PATH" {
props.Set(SslKeyPathKey, value)
} else if key == "STAT_DIR" {
props.Set(StatDirKey, value)
} else if key == "STAT_ENABLE" {
props.Set(StatEnableKey, value)
} else if key == "STAT_FLUSH_FREQ" {
props.Set(StatFlushFreqKey, value)
} else if key == "STAT_HIGH_FREQ_SQL_COUNT" {
props.Set(StatHighFreqSqlCountKey, value)
} else if key == "STAT_SLOW_SQL_COUNT" {
props.Set(StatSlowSqlCountKey, value)
} else if key == "STAT_SQL_MAX_COUNT" {
props.Set(StatSqlMaxCountKey, value)
} else if key == "STAT_SQL_REMOVE_MODE" {
props.Set(StatSqlRemoveModeKey, value)
} else if key == "SWITCH_INTERVAL" {
props.Set(SwitchIntervalKey, value)
} else if key == "SWITCH_TIME" ||
key == "SWITCH_TIMES" {
props.Set(SwitchTimesKey, value)
} else if key == "TIME_ZONE" {
props.Set(TimeZoneKey, value)
props.Set("localTimezone", value)
} else if key == "USER_REMAP" {
tmp := props.GetString(UserRemapKey, "")
props.Set(UserRemapKey, tmp+"("+value+")")
} else if key == "SERVER_OPTION" {
props.Set(ServerOptionKey, value)
} else if key == "CLOB_TO_BYTES" {
props.Set(ClobToBytesKey, value)
} else {
return false
}
return true
}
func parseServerName(name string, value string) *epGroup {
values := strings.Split(value, ",")
var tmpVals []string
var tmpName string
var tmpPort int
var svrList = make([]*ep, 0, len(values))
for _, v := range values {
var tmp *ep
// 先查找IPV6,以[]包括
begin := strings.IndexByte(v, '[')
end := -1
if begin != -1 {
end = strings.IndexByte(v[begin:], ']')
}
if end != -1 {
//tmpName = v[begin+1 : end]
tmpName = v[begin : end+1]
// port
if portIndex := strings.IndexByte(v[end:], ':'); portIndex != -1 {
tmpPort, _ = strconv.Atoi(strings.TrimSpace(v[end+portIndex+1:]))
} else {
tmpPort = int(DEFAULT_PORT)
}
tmp = newEP(tmpName, int32(tmpPort))
svrList = append(svrList, tmp)
continue
}
// IPV4
tmpVals = strings.Split(v, ":")
tmpName = strings.TrimSpace(tmpVals[0])
if len(tmpVals) >= 2 {
tmpPort, _ = strconv.Atoi(tmpVals[1])
} else {
tmpPort = int(DEFAULT_PORT)
}
tmp = newEP(tmpName, int32(tmpPort))
svrList = append(svrList, tmp)
}
if len(svrList) == 0 {
return nil
}
return newEPGroup(name, svrList)
}
func setDriverAttributes(props *Properties) {
if props == nil || props.Len() == 0 {
return
}
parseLanguage(props.GetString(LanguageKey, "cn"))
DbAliveCheckFreq = props.GetInt(DbAliveCheckFreqKey, DbAliveCheckFreqDef, 1, int(INT32_MAX))
//// log
//LogLevel = ParseLogLevel(props)
//LogDir = util.StringUtil.FormatDir(props.GetTrimString(LogDirKey, LogDirDef))
//LogBufferSize = props.GetInt(LogBufferSizeKey, LogBufferSizeDef, 1, int(INT32_MAX))
//LogFlushFreq = props.GetInt(LogFlushFreqKey, LogFlushFreqDef, 1, int(INT32_MAX))
//LogFlushQueueSize = props.GetInt(LogFlusherQueueSizeKey, LogFlushQueueSizeDef, 1, int(INT32_MAX))
//
//// stat
//StatEnable = props.GetBool(StatEnableKey, StatEnableDef)
//StatDir = util.StringUtil.FormatDir(props.GetTrimString(StatDirKey, StatDirDef))
//StatFlushFreq = props.GetInt(StatFlushFreqKey, StatFlushFreqDef, 1, int(INT32_MAX))
//StatHighFreqSqlCount = props.GetInt(StatHighFreqSqlCountKey, StatHighFreqSqlCountDef, 0, 1000)
//StatSlowSqlCount = props.GetInt(StatSlowSqlCountKey, StatSlowSqlCountDef, 0, 1000)
//StatSqlMaxCount = props.GetInt(StatSqlMaxCountKey, StatSqlMaxCountDef, 0, 100000)
//parseStatSqlRemoveMode(props)
}
func parseLanguage(value string) {
if util.StringUtil.EqualsIgnoreCase("cn", value) {
Locale = 0
} else if util.StringUtil.EqualsIgnoreCase("en", value) {
Locale = 1
} else if util.StringUtil.EqualsIgnoreCase("cnt_hk", value) ||
util.StringUtil.EqualsIgnoreCase("hk", value) ||
util.StringUtil.EqualsIgnoreCase("tw", value) {
Locale = 2
}
}
func IsSupportedCharset(charset string) bool {
if util.StringUtil.EqualsIgnoreCase(ENCODING_UTF8, charset) ||
util.StringUtil.EqualsIgnoreCase(ENCODING_GB18030, charset) ||
util.StringUtil.EqualsIgnoreCase(ENCODING_EUCKR, charset) ||
util.StringUtil.EqualsIgnoreCase(ENCODING_BIG5, charset) {
return true
}
return false
}
func ParseLogLevel(props *Properties) int {
logLevel := LOG_OFF
value := props.GetString(LogLevelKey, "")
if value != "" && !util.StringUtil.IsDigit(value) {
if util.StringUtil.EqualsIgnoreCase("debug", value) {
logLevel = LOG_DEBUG
} else if util.StringUtil.EqualsIgnoreCase("info", value) {
logLevel = LOG_INFO
} else if util.StringUtil.EqualsIgnoreCase("sql", value) {
logLevel = LOG_SQL
} else if util.StringUtil.EqualsIgnoreCase("warn", value) {
logLevel = LOG_WARN
} else if util.StringUtil.EqualsIgnoreCase("error", value) {
logLevel = LOG_ERROR
} else if util.StringUtil.EqualsIgnoreCase("off", value) {
logLevel = LOG_OFF
} else if util.StringUtil.EqualsIgnoreCase("all", value) {
logLevel = LOG_ALL
}
} else {
logLevel = props.GetInt(LogLevelKey, logLevel, LOG_OFF, LOG_INFO)
}
return logLevel
}
+450
View File
@@ -0,0 +1,450 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"database/sql"
"database/sql/driver"
"math"
"reflect"
"strings"
"time"
)
const (
INT8_MAX int8 = math.MaxInt8
INT8_MIN int8 = math.MinInt8
BYTE_MAX byte = math.MaxUint8
BYTE_MIN byte = 0
INT16_MAX int16 = math.MaxInt16
INT16_MIN int16 = math.MinInt16
UINT16_MAX uint16 = math.MaxUint16
UINT16_MIN uint16 = 0
INT32_MAX int32 = math.MaxInt32
INT32_MIN int32 = math.MinInt32
UINT32_MAX uint32 = math.MaxUint32
UINT32_MIN uint32 = 0
INT64_MAX int64 = math.MaxInt64
INT64_MIN int64 = math.MinInt64
UINT64_MAX uint64 = math.MaxUint64
UINT64_MIN uint64 = 0
FLOAT32_MAX float32 = 3.4e+38
FLOAT32_MIN float32 = -3.4e+38
BYTE_SIZE = 1
USINT_SIZE = 2
ULINT_SIZE = 4
DDWORD_SIZE = 8
LINT64_SIZE = 8
CHAR = 0
VARCHAR2 = 1
VARCHAR = 2
BIT = 3
TINYINT = 5
SMALLINT = 6
INT = 7
BIGINT = 8
DECIMAL = 9
REAL = 10
DOUBLE = 11
BLOB = 12
BOOLEAN = 13
DATE = 14
TIME = 15
DATETIME = 16
BINARY = 17
VARBINARY = 18
CLOB = 19
INTERVAL_YM = 20
INTERVAL_DT = 21
TIME_TZ = 22
DATETIME_TZ = 23
XDEC_INT32 = 24
XDEC_INT64 = 25
DATETIME2 = 26
DATETIME2_TZ = 27
NULL = 28
ANY = 31
STAR_ALL = 32
STAR = 33
RECORD = 40
TYPE = 41
TYPE_REF = 42
UNKNOWN = 54
ARRAY = 117
CLASS = 119
CURSOR = 120
PLTYPE_RECORD = 121
SARRAY = 122
CURSOR_ORACLE = -10
BIT_PREC = BYTE_SIZE
TINYINT_PREC = BYTE_SIZE
SMALLINT_PREC = USINT_SIZE
INT_PREC = ULINT_SIZE
BIGINT_PREC = LINT64_SIZE
REAL_PREC = 4
DOUBLE_PREC = 8
DATE_PREC = 3
TIME_PREC = 5
DATETIME_PREC = 8
DATETIME2_PREC = 9
TIME_TZ_PREC = TIME_PREC + 2
DATETIME_TZ_PREC = DATETIME_PREC + 2
DATETIME2_TZ_PREC = DATETIME2_PREC + 2
INTERVAL_YM_PREC = 3 * ULINT_SIZE
INTERVAL_DT_PREC = 6 * ULINT_SIZE
VARCHAR_PREC = 8188
VARBINARY_PREC = 8188
BLOB_PREC int32 = INT32_MAX
CLOB_PREC int32 = INT32_MAX
NULL_PREC = 0
LOCAL_TIME_ZONE_SCALE_MASK = 0x00001000
BFILE_PREC = 512
BFILE_SCALE = 6
COMPLEX_SCALE = 5
CURRENCY_PREC = 19
CURRENCY_SCALE = 4
LOCAL_DATETIME_SCALE_MASK int32 = 0x00001000
ORACLE_FLOAT_SCALE_MASK int32 = 0x81
ORACLE_DATE_SCALE_MASK int32 = 0x00002000
)
func isComplexType(colType int, scale int) bool {
return (colType == BLOB && scale == COMPLEX_SCALE) || colType == ARRAY || colType == SARRAY || colType == CLASS || colType == PLTYPE_RECORD
}
func isLocalTimeZone(colType int, scale int) bool {
return (colType == DATETIME || colType == DATETIME2) && (scale&LOCAL_TIME_ZONE_SCALE_MASK) != 0
}
func getLocalTimeZoneScale(colType int, scale int) int {
return scale & (^LOCAL_TIME_ZONE_SCALE_MASK)
}
func isFloat(colType int, scale int) bool {
return colType == DECIMAL && scale == int(ORACLE_FLOAT_SCALE_MASK)
}
func getFloatPrec(prec int) int {
return int(math.Round(float64(prec)*0.30103)) + 1
}
func getFloatScale(scale int) int {
return scale & (^int(ORACLE_FLOAT_SCALE_MASK))
}
var (
scanTypeFloat32 = reflect.TypeOf(float32(0))
scanTypeFloat64 = reflect.TypeOf(float64(0))
scanTypeBool = reflect.TypeOf(false)
scanTypeInt8 = reflect.TypeOf(int8(0))
scanTypeInt16 = reflect.TypeOf(int16(0))
scanTypeInt32 = reflect.TypeOf(int32(0))
scanTypeInt64 = reflect.TypeOf(int64(0))
scanTypeNullBool = reflect.TypeOf(sql.NullBool{})
scanTypeNullFloat = reflect.TypeOf(sql.NullFloat64{})
scanTypeNullInt = reflect.TypeOf(sql.NullInt64{})
scanTypeNullString = reflect.TypeOf(sql.NullString{})
scanTypeNullTime = reflect.TypeOf(sql.NullTime{})
scanTypeRawBytes = reflect.TypeOf(sql.RawBytes{})
scanTypeString = reflect.TypeOf("")
scanTypeTime = reflect.TypeOf(time.Now())
scanTypeUnknown = reflect.TypeOf(new(interface{}))
)
func (column *column) ScanType() reflect.Type {
switch column.colType {
case BOOLEAN:
if column.nullable {
return scanTypeNullBool
}
return scanTypeBool
case BIT:
if strings.ToLower(column.typeName) == "boolean" {
if column.nullable {
return scanTypeNullBool
}
return scanTypeBool
} else {
if column.nullable {
return scanTypeNullInt
}
return scanTypeInt8
}
case TINYINT:
if column.nullable {
return scanTypeNullInt
}
return scanTypeInt8
case SMALLINT:
if column.nullable {
return scanTypeNullInt
}
return scanTypeInt16
case INT:
if column.nullable {
return scanTypeNullInt
}
return scanTypeInt32
case BIGINT:
if column.nullable {
return scanTypeNullInt
}
return scanTypeInt64
case REAL:
if column.nullable {
return scanTypeNullFloat
}
return scanTypeFloat32
case DOUBLE:
if strings.ToLower(column.typeName) == "float" {
if column.nullable {
return scanTypeNullFloat
}
return scanTypeFloat32
}
if column.nullable {
return scanTypeNullFloat
}
return scanTypeFloat64
case DATE, TIME, TIME_TZ, DATETIME, DATETIME_TZ, DATETIME2, DATETIME2_TZ:
if column.nullable {
return scanTypeNullTime
}
return scanTypeTime
case DECIMAL, BINARY, VARBINARY, BLOB:
return scanTypeRawBytes
case CHAR, VARCHAR2, VARCHAR, CLOB:
if column.nullable {
return scanTypeNullString
}
return scanTypeString
}
return scanTypeUnknown
}
func (column *column) Length() (length int64, ok bool) {
switch column.colType {
case BINARY, VARBINARY, BLOB, CHAR, VARCHAR2, VARCHAR, CLOB:
return int64(column.prec), true
}
return int64(0), false
}
func (column *column) PrecisionScale() (precision, scale int64, ok bool) {
switch column.colType {
case DECIMAL:
if column.prec == 0 {
return 38, int64(column.scale), true
} else {
return int64(column.prec), int64(column.scale), true
}
}
return int64(0), int64(0), false
}
func (column *column) getColumnData(bytes []byte, conn *DmConnection) (driver.Value, error) {
if bytes == nil {
return nil, nil
}
switch column.colType {
case BOOLEAN:
return bytes[0] != 0, nil
case BIT:
if strings.ToLower(column.typeName) == "boolean" {
return bytes[0] != 0, nil
}
return int8(bytes[0]), nil
case TINYINT:
return int8(bytes[0]), nil
case SMALLINT:
return Dm_build_1346.Dm_build_1443(bytes, 0), nil
case INT:
return Dm_build_1346.Dm_build_1448(bytes, 0), nil
case BIGINT:
return Dm_build_1346.Dm_build_1453(bytes, 0), nil
case REAL:
return Dm_build_1346.Dm_build_1458(bytes, 0), nil
case DOUBLE:
return Dm_build_1346.Dm_build_1462(bytes, 0), nil
case DATE, TIME, DATETIME, TIME_TZ, DATETIME_TZ, DATETIME2, DATETIME2_TZ:
return DB2G.toTime(bytes, column, conn)
case INTERVAL_DT:
return newDmIntervalDTByBytes(bytes).String(), nil
case INTERVAL_YM:
return newDmIntervalYMByBytes(bytes).String(), nil
case DECIMAL:
tmp, err := DB2G.toDmDecimal(bytes, column, conn)
if err != nil {
return nil, err
}
return tmp.String(), nil
case BINARY, VARBINARY:
return bytes, nil
case BLOB:
if isComplexType(int(column.colType), int(column.scale)) {
return DB2G.toComplexType(bytes, column, conn)
}
blob := DB2G.toDmBlob(bytes, column, conn)
l, err := blob.GetLength()
if err != nil {
return nil, err
}
return blob.getBytes(1, int32(l))
case CHAR, VARCHAR2, VARCHAR:
return Dm_build_1346.Dm_build_1503(bytes, 0, len(bytes), conn.getServerEncoding(), conn), nil
case CLOB:
clob := DB2G.toDmClob(bytes, conn, column)
l, err := clob.GetLength()
if err != nil {
return nil, err
}
str, err := clob.getSubString(1, int32(l))
if err != nil {
return str, err
}
if conn.dmConnector.clobToBytes {
return []byte(str), err
} else {
return str, err
}
}
return string(bytes), nil
}
func emptyStringToNil(t int32) bool {
switch t {
case BOOLEAN, BIT, TINYINT, SMALLINT, INT, BIGINT, REAL, DOUBLE, DECIMAL, DATE, TIME,
DATETIME, INTERVAL_DT, INTERVAL_YM, TIME_TZ, DATETIME_TZ, DATETIME2, DATETIME2_TZ:
return true
default:
return false
}
}
+1389
View File
File diff suppressed because it is too large Load Diff
+763
View File
@@ -0,0 +1,763 @@
/*
* Copyright (c) 2000-2018, 达梦数据库有限公司.
* All rights reserved.
*/
package dm
import (
"database/sql/driver"
)
const (
OBJ_BLOB_MAGIC = 78111999
CLTN_TYPE_IND_TABLE = 3
CLTN_TYPE_NST_TABLE = 2
CLTN_TYPE_VARRAY = 1
)
type TypeDescriptor struct {
column *column
m_sqlName *sqlName
m_objId int
m_objVersion int
m_outerId int
m_outerVer int
m_subId int
m_cltnType int
m_maxCnt int
m_length int
m_size int
m_conn *DmConnection
m_serverEncoding string
m_arrObj *TypeDescriptor
m_fieldsObj []TypeDescriptor
m_descBuf []byte
}
func newTypeDescriptorWithFulName(fulName string, conn *DmConnection) *TypeDescriptor {
td := new(TypeDescriptor)
td.init()
td.m_sqlName = newSqlNameByFulName(fulName)
td.m_conn = conn
return td
}
func newTypeDescriptor(conn *DmConnection) *TypeDescriptor {
td := new(TypeDescriptor)
td.init()
td.m_sqlName = newSqlNameByConn(conn)
td.m_conn = conn
return td
}
func (typeDescriptor *TypeDescriptor) init() {
typeDescriptor.column = new(column).InitColumn()
typeDescriptor.m_sqlName = nil
typeDescriptor.m_objId = -1
typeDescriptor.m_objVersion = -1
typeDescriptor.m_outerId = 0
typeDescriptor.m_outerVer = 0
typeDescriptor.m_subId = 0
typeDescriptor.m_cltnType = 0
typeDescriptor.m_maxCnt = 0
typeDescriptor.m_length = 0
typeDescriptor.m_size = 0
typeDescriptor.m_conn = nil
typeDescriptor.m_serverEncoding = ""
typeDescriptor.m_arrObj = nil
typeDescriptor.m_fieldsObj = nil
typeDescriptor.m_descBuf = nil
}
func (typeDescriptor *TypeDescriptor) parseDescByName() error {
sql := "BEGIN ? = SF_DESCRIBE_TYPE(?); END;"
params := make([]driver.Value, 2)
params[1] = typeDescriptor.m_sqlName.m_fulName
rs, err := typeDescriptor.m_conn.query(sql, params)
if err != nil {
return err
}
rs.close()
l, err := params[0].(*DmBlob).GetLength()
if err != nil {
return err
}
buf, err := params[0].(*DmBlob).getBytes(1, int32(l))
if err != nil {
return err
}
typeDescriptor.m_serverEncoding = typeDescriptor.m_conn.getServerEncoding()
err = typeDescriptor.unpack(Dm_build_83(buf))
if err != nil {
return err
}
return nil
}
func (typeDescriptor *TypeDescriptor) getFulName() (string, error) {
return typeDescriptor.m_sqlName.getFulName()
}
func (typeDescriptor *TypeDescriptor) getDType() int {
return int(typeDescriptor.column.colType)
}
func (typeDescriptor *TypeDescriptor) getPrec() int {
return int(typeDescriptor.column.prec)
}
func (typeDescriptor *TypeDescriptor) getScale() int {
return int(typeDescriptor.column.scale)
}
func (typeDescriptor *TypeDescriptor) getServerEncoding() string {
if typeDescriptor.m_serverEncoding == "" {
return typeDescriptor.m_conn.getServerEncoding()
} else {
return typeDescriptor.m_serverEncoding
}
}
func (typeDescriptor *TypeDescriptor) getObjId() int {
return typeDescriptor.m_objId
}
func (typeDescriptor *TypeDescriptor) getStaticArrayLength() int {
return typeDescriptor.m_length
}
func (typeDescriptor *TypeDescriptor) getStrctMemSize() int {
return typeDescriptor.m_size
}
func (typeDescriptor *TypeDescriptor) getOuterId() int {
return typeDescriptor.m_outerId
}
func (typeDescriptor *TypeDescriptor) getCltnType() int {
return typeDescriptor.m_cltnType
}
func (typeDescriptor *TypeDescriptor) getMaxCnt() int {
return typeDescriptor.m_maxCnt
}
func getPackSize(typeDesc *TypeDescriptor) (int, error) {
len := 0
switch typeDesc.column.colType {
case ARRAY, SARRAY:
return getPackArraySize(typeDesc)
case CLASS:
return getPackClassSize(typeDesc)
case PLTYPE_RECORD:
return getPackRecordSize(typeDesc)
}
len += ULINT_SIZE
len += ULINT_SIZE
len += ULINT_SIZE
return len, nil
}
func pack(typeDesc *TypeDescriptor, msg *Dm_build_78) error {
switch typeDesc.column.colType {
case ARRAY, SARRAY:
return packArray(typeDesc, msg)
case CLASS:
return packClass(typeDesc, msg)
case PLTYPE_RECORD:
return packRecord(typeDesc, msg)
}
msg.Dm_build_133(typeDesc.column.colType)
msg.Dm_build_133(typeDesc.column.prec)
msg.Dm_build_133(typeDesc.column.scale)
return nil
}
func getPackArraySize(arrDesc *TypeDescriptor) (int, error) {
l := 0
l += ULINT_SIZE
name := arrDesc.m_sqlName.m_name
l += USINT_SIZE
serverEncoding := arrDesc.getServerEncoding()
ret := Dm_build_1346.Dm_build_1562(name, serverEncoding, arrDesc.m_conn)
l += len(ret)
l += ULINT_SIZE
l += ULINT_SIZE
l += ULINT_SIZE
i, err := getPackSize(arrDesc.m_arrObj)
if err != nil {
return 0, err
}
l += i
return l, nil
}
func packArray(arrDesc *TypeDescriptor, msg *Dm_build_78) error {
msg.Dm_build_133(arrDesc.column.colType)
msg.Dm_build_189(arrDesc.m_sqlName.m_name, arrDesc.getServerEncoding(), arrDesc.m_conn)
msg.Dm_build_133(int32(arrDesc.m_objId))
msg.Dm_build_133(int32(arrDesc.m_objVersion))
msg.Dm_build_133(int32(arrDesc.m_length))
return pack(arrDesc.m_arrObj, msg)
}
func packRecord(strctDesc *TypeDescriptor, msg *Dm_build_78) error {
msg.Dm_build_133(strctDesc.column.colType)
msg.Dm_build_189(strctDesc.m_sqlName.m_name, strctDesc.getServerEncoding(), strctDesc.m_conn)
msg.Dm_build_133(int32(strctDesc.m_objId))
msg.Dm_build_133(int32(strctDesc.m_objVersion))
msg.Dm_build_129(int16(strctDesc.m_size))
for i := 0; i < strctDesc.m_size; i++ {
err := pack(&strctDesc.m_fieldsObj[i], msg)
if err != nil {
return err
}
}
return nil
}
func getPackRecordSize(strctDesc *TypeDescriptor) (int, error) {
l := 0
l += ULINT_SIZE
name := strctDesc.m_sqlName.m_name
l += USINT_SIZE
serverEncoding := strctDesc.getServerEncoding()
ret := Dm_build_1346.Dm_build_1562(name, serverEncoding, strctDesc.m_conn)
l += len(ret)
l += ULINT_SIZE
l += ULINT_SIZE
l += USINT_SIZE
for i := 0; i < strctDesc.m_size; i++ {
i, err := getPackSize(&strctDesc.m_fieldsObj[i])
if err != nil {
return 0, err
}
l += i
}
return l, nil
}
func getPackClassSize(strctDesc *TypeDescriptor) (int, error) {
l := 0
l += ULINT_SIZE
name := strctDesc.m_sqlName.m_name
l += USINT_SIZE
serverEncoding := strctDesc.getServerEncoding()
ret := Dm_build_1346.Dm_build_1562(name, serverEncoding, strctDesc.m_conn)
l += len(ret)
l += ULINT_SIZE
l += ULINT_SIZE
if strctDesc.m_objId == 4 {
l += ULINT_SIZE
l += ULINT_SIZE
l += USINT_SIZE
}
return l, nil
}
func packClass(strctDesc *TypeDescriptor, msg *Dm_build_78) error {
msg.Dm_build_133(strctDesc.column.colType)
msg.Dm_build_189(strctDesc.m_sqlName.m_name, strctDesc.getServerEncoding(), strctDesc.m_conn)
msg.Dm_build_133(int32(strctDesc.m_objId))
msg.Dm_build_133(int32(strctDesc.m_objVersion))
if strctDesc.m_objId == 4 {
msg.Dm_build_133(int32(strctDesc.m_outerId))
msg.Dm_build_133(int32(strctDesc.m_outerVer))
msg.Dm_build_141(uint16(strctDesc.m_subId))
}
return nil
}
func (typeDescriptor *TypeDescriptor) unpack(buffer *Dm_build_78) error {
typeDescriptor.column.colType = buffer.Dm_build_207()
switch typeDescriptor.column.colType {
case ARRAY, SARRAY:
return typeDescriptor.unpackArray(buffer)
case CLASS:
return typeDescriptor.unpackClass(buffer)
case PLTYPE_RECORD:
return typeDescriptor.unpackRecord(buffer)
}
typeDescriptor.column.prec = buffer.Dm_build_207()
typeDescriptor.column.scale = buffer.Dm_build_207()
return nil
}
func (typeDescriptor *TypeDescriptor) unpackArray(buffer *Dm_build_78) error {
typeDescriptor.m_sqlName.m_name = buffer.Dm_build_257(typeDescriptor.getServerEncoding(), typeDescriptor.m_conn)
typeDescriptor.m_sqlName.m_schId = int(buffer.Dm_build_207())
typeDescriptor.m_sqlName.m_packId = int(buffer.Dm_build_207())
typeDescriptor.m_objId = int(buffer.Dm_build_207())
typeDescriptor.m_objVersion = int(buffer.Dm_build_207())
typeDescriptor.m_length = int(buffer.Dm_build_207())
if typeDescriptor.column.colType == ARRAY {
typeDescriptor.m_length = 0
}
typeDescriptor.m_arrObj = newTypeDescriptor(typeDescriptor.m_conn)
return typeDescriptor.m_arrObj.unpack(buffer)
}
func (typeDescriptor *TypeDescriptor) unpackRecord(buffer *Dm_build_78) error {
typeDescriptor.m_sqlName.m_name = buffer.Dm_build_257(typeDescriptor.getServerEncoding(), typeDescriptor.m_conn)
typeDescriptor.m_sqlName.m_schId = int(buffer.Dm_build_207())
typeDescriptor.m_sqlName.m_packId = int(buffer.Dm_build_207())
typeDescriptor.m_objId = int(buffer.Dm_build_207())
typeDescriptor.m_objVersion = int(buffer.Dm_build_207())
typeDescriptor.m_size = int(buffer.Dm_build_222())
typeDescriptor.m_fieldsObj = make([]TypeDescriptor, typeDescriptor.m_size)
for i := 0; i < typeDescriptor.m_size; i++ {
typeDescriptor.m_fieldsObj[i] = *newTypeDescriptor(typeDescriptor.m_conn)
typeDescriptor.m_fieldsObj[i].unpack(buffer)
}
return nil
}
func (typeDescriptor *TypeDescriptor) unpackClnt_nestTab(buffer *Dm_build_78) error {
typeDescriptor.m_maxCnt = int(buffer.Dm_build_207())
typeDescriptor.m_arrObj = newTypeDescriptor(typeDescriptor.m_conn)
typeDescriptor.m_arrObj.unpack(buffer)
return nil
}
func (typeDescriptor *TypeDescriptor) unpackClnt(buffer *Dm_build_78) error {
typeDescriptor.m_outerId = int(buffer.Dm_build_207())
typeDescriptor.m_outerVer = int(buffer.Dm_build_207())
typeDescriptor.m_subId = int(buffer.Dm_build_222())
typeDescriptor.m_cltnType = int(buffer.Dm_build_222())
switch typeDescriptor.m_cltnType {
case CLTN_TYPE_IND_TABLE:
return ECGO_UNSUPPORTED_TYPE.throw()
case CLTN_TYPE_NST_TABLE, CLTN_TYPE_VARRAY:
return typeDescriptor.unpackClnt_nestTab(buffer)
}
return nil
}
func (typeDescriptor *TypeDescriptor) unpackClass(buffer *Dm_build_78) error {
typeDescriptor.m_sqlName.m_name = buffer.Dm_build_257(typeDescriptor.getServerEncoding(), typeDescriptor.m_conn)
typeDescriptor.m_sqlName.m_schId = int(buffer.Dm_build_207())
typeDescriptor.m_sqlName.m_packId = int(buffer.Dm_build_207())
typeDescriptor.m_objId = int(buffer.Dm_build_207())
typeDescriptor.m_objVersion = int(buffer.Dm_build_207())
if typeDescriptor.m_objId == 4 {
return typeDescriptor.unpackClnt(buffer)
} else {
typeDescriptor.m_size = int(buffer.Dm_build_222())
typeDescriptor.m_fieldsObj = make([]TypeDescriptor, typeDescriptor.m_size)
for i := 0; i < typeDescriptor.m_size; i++ {
typeDescriptor.m_fieldsObj[i] = *newTypeDescriptor(typeDescriptor.m_conn)
err := typeDescriptor.m_fieldsObj[i].unpack(buffer)
if err != nil {
return err
}
}
return nil
}
}
func calcChkDescLen_array(desc *TypeDescriptor) (int, error) {
offset := 0
offset += USINT_SIZE
offset += ULINT_SIZE
tmp, err := calcChkDescLen(desc)
if err != nil {
return 0, err
}
offset += tmp
return offset, nil
}
func calcChkDescLen_record(desc *TypeDescriptor) (int, error) {
offset := 0
offset += USINT_SIZE
offset += USINT_SIZE
for i := 0; i < desc.m_size; i++ {
tmp, err := calcChkDescLen(&desc.m_fieldsObj[i])
if err != nil {
return 0, err
}
offset += tmp
}
return offset, nil
}
func calcChkDescLen_class_normal(desc *TypeDescriptor) (int, error) {
offset := 0
offset += USINT_SIZE
for i := 0; i < desc.m_size; i++ {
tmp, err := calcChkDescLen(&desc.m_fieldsObj[i])
if err != nil {
return 0, err
}
offset += tmp
}
return offset, nil
}
func calcChkDescLen_class_cnlt(desc *TypeDescriptor) (int, error) {
offset := 0
offset += USINT_SIZE
offset += ULINT_SIZE
switch desc.getCltnType() {
case CLTN_TYPE_IND_TABLE:
return 0, ECGO_UNSUPPORTED_TYPE.throw()
case CLTN_TYPE_VARRAY, CLTN_TYPE_NST_TABLE:
i, err := calcChkDescLen(desc.m_arrObj)
if err != nil {
return 0, err
}
offset += i
}
return offset, nil
}
func calcChkDescLen_class(desc *TypeDescriptor) (int, error) {
offset := 0
offset += USINT_SIZE
offset += BYTE_SIZE
if desc.m_objId == 4 {
i, err := calcChkDescLen_class_cnlt(desc)
if err != nil {
return 0, err
}
offset += i
} else {
i, err := calcChkDescLen_class_normal(desc)
if err != nil {
return 0, err
}
offset += i
}
return offset, nil
}
func calcChkDescLen_buildin() int {
offset := 0
offset += USINT_SIZE
offset += USINT_SIZE
offset += USINT_SIZE
return offset
}
func calcChkDescLen(desc *TypeDescriptor) (int, error) {
switch desc.getDType() {
case ARRAY, SARRAY:
return calcChkDescLen_array(desc)
case PLTYPE_RECORD:
return calcChkDescLen_record(desc)
case CLASS:
return calcChkDescLen_class(desc)
default:
return calcChkDescLen_buildin(), nil
}
}
func (typeDescriptor *TypeDescriptor) makeChkDesc_array(offset int, desc *TypeDescriptor) (int, error) {
Dm_build_1346.Dm_build_1357(typeDescriptor.m_descBuf, offset, ARRAY)
offset += USINT_SIZE
Dm_build_1346.Dm_build_1362(typeDescriptor.m_descBuf, offset, int32(desc.m_length))
offset += ULINT_SIZE
return typeDescriptor.makeChkDesc(offset, desc)
}
func (typeDescriptor *TypeDescriptor) makeChkDesc_record(offset int, desc *TypeDescriptor) (int, error) {
Dm_build_1346.Dm_build_1357(typeDescriptor.m_descBuf, offset, PLTYPE_RECORD)
offset += USINT_SIZE
Dm_build_1346.Dm_build_1357(typeDescriptor.m_descBuf, offset, int16(desc.m_size))
offset += USINT_SIZE
var err error
for i := 0; i < desc.m_size; i++ {
offset, err = typeDescriptor.makeChkDesc(offset, &desc.m_fieldsObj[i])
if err != nil {
return 0, err
}
}
return offset, nil
}
func (typeDescriptor *TypeDescriptor) makeChkDesc_buildin(offset int, desc *TypeDescriptor) int {
dtype := int16(desc.getDType())
prec := 0
scale := 0
if dtype != BLOB {
prec = desc.getPrec()
scale = desc.getScale()
}
Dm_build_1346.Dm_build_1357(typeDescriptor.m_descBuf, offset, dtype)
offset += USINT_SIZE
Dm_build_1346.Dm_build_1357(typeDescriptor.m_descBuf, offset, int16(prec))
offset += USINT_SIZE
Dm_build_1346.Dm_build_1357(typeDescriptor.m_descBuf, offset, int16(scale))
offset += USINT_SIZE
return offset
}
func (typeDescriptor *TypeDescriptor) makeChkDesc_class_normal(offset int, desc *TypeDescriptor) (int, error) {
Dm_build_1346.Dm_build_1357(typeDescriptor.m_descBuf, offset, int16(desc.m_size))
offset += USINT_SIZE
var err error
for i := 0; i < desc.m_size; i++ {
offset, err = typeDescriptor.makeChkDesc(offset, &desc.m_fieldsObj[i])
if err != nil {
return 0, err
}
}
return offset, nil
}
func (typeDescriptor *TypeDescriptor) makeChkDesc_class_clnt(offset int, desc *TypeDescriptor) (int, error) {
Dm_build_1346.Dm_build_1357(typeDescriptor.m_descBuf, offset, int16(desc.m_cltnType))
offset += USINT_SIZE
Dm_build_1346.Dm_build_1362(typeDescriptor.m_descBuf, offset, int32(desc.getMaxCnt()))
offset += ULINT_SIZE
switch desc.m_cltnType {
case CLTN_TYPE_IND_TABLE:
return 0, ECGO_UNSUPPORTED_TYPE.throw()
case CLTN_TYPE_NST_TABLE, CLTN_TYPE_VARRAY:
return typeDescriptor.makeChkDesc(offset, desc.m_arrObj)
}
return offset, nil
}
func (typeDescriptor *TypeDescriptor) makeChkDesc_class(offset int, desc *TypeDescriptor) (int, error) {
Dm_build_1346.Dm_build_1357(typeDescriptor.m_descBuf, offset, CLASS)
offset += USINT_SIZE
isClnt := false
if desc.m_objId == 4 {
isClnt = true
}
if isClnt {
Dm_build_1346.Dm_build_1347(typeDescriptor.m_descBuf, offset, byte(1))
} else {
Dm_build_1346.Dm_build_1347(typeDescriptor.m_descBuf, offset, byte(0))
}
offset += BYTE_SIZE
if isClnt {
return typeDescriptor.makeChkDesc_class_clnt(offset, desc)
} else {
return typeDescriptor.makeChkDesc_class_normal(offset, desc)
}
}
func (typeDescriptor *TypeDescriptor) makeChkDesc(offset int, subDesc *TypeDescriptor) (int, error) {
switch subDesc.getDType() {
case ARRAY, SARRAY:
return typeDescriptor.makeChkDesc_array(offset, subDesc)
case PLTYPE_RECORD:
return typeDescriptor.makeChkDesc_record(offset, subDesc)
case CLASS:
return typeDescriptor.makeChkDesc_class(offset, subDesc)
default:
return typeDescriptor.makeChkDesc_buildin(offset, subDesc), nil
}
}
func (typeDescriptor *TypeDescriptor) getClassDescChkInfo() ([]byte, error) {
if typeDescriptor.m_descBuf != nil {
return typeDescriptor.m_descBuf, nil
}
l, err := calcChkDescLen(typeDescriptor)
if err != nil {
return nil, err
}
typeDescriptor.m_descBuf = make([]byte, l)
typeDescriptor.makeChkDesc(0, typeDescriptor)
return typeDescriptor.m_descBuf, nil
}
+249
View File
@@ -0,0 +1,249 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:generate go run maketables.go
// Package charmap provides simple character encodings such as IBM Code Page 437
// and Windows 1252.
package charmap // import "golang.org/x/text/encoding/charmap"
import (
"unicode/utf8"
"golang.org/x/text/encoding"
"golang.org/x/text/encoding/internal"
"golang.org/x/text/encoding/internal/identifier"
"golang.org/x/text/transform"
)
// These encodings vary only in the way clients should interpret them. Their
// coded character set is identical and a single implementation can be shared.
var (
// ISO8859_6E is the ISO 8859-6E encoding.
ISO8859_6E encoding.Encoding = &iso8859_6E
// ISO8859_6I is the ISO 8859-6I encoding.
ISO8859_6I encoding.Encoding = &iso8859_6I
// ISO8859_8E is the ISO 8859-8E encoding.
ISO8859_8E encoding.Encoding = &iso8859_8E
// ISO8859_8I is the ISO 8859-8I encoding.
ISO8859_8I encoding.Encoding = &iso8859_8I
iso8859_6E = internal.Encoding{
Encoding: ISO8859_6,
Name: "ISO-8859-6E",
MIB: identifier.ISO88596E,
}
iso8859_6I = internal.Encoding{
Encoding: ISO8859_6,
Name: "ISO-8859-6I",
MIB: identifier.ISO88596I,
}
iso8859_8E = internal.Encoding{
Encoding: ISO8859_8,
Name: "ISO-8859-8E",
MIB: identifier.ISO88598E,
}
iso8859_8I = internal.Encoding{
Encoding: ISO8859_8,
Name: "ISO-8859-8I",
MIB: identifier.ISO88598I,
}
)
// All is a list of all defined encodings in this package.
var All []encoding.Encoding = listAll
// TODO: implement these encodings, in order of importance.
// ASCII, ISO8859_1: Rather common. Close to Windows 1252.
// ISO8859_9: Close to Windows 1254.
// utf8Enc holds a rune's UTF-8 encoding in data[:len].
type utf8Enc struct {
len uint8
data [3]byte
}
// Charmap is an 8-bit character set encoding.
type Charmap struct {
// name is the encoding's name.
name string
// mib is the encoding type of this encoder.
mib identifier.MIB
// asciiSuperset states whether the encoding is a superset of ASCII.
asciiSuperset bool
// low is the lower bound of the encoded byte for a non-ASCII rune. If
// Charmap.asciiSuperset is true then this will be 0x80, otherwise 0x00.
low uint8
// replacement is the encoded replacement character.
replacement byte
// decode is the map from encoded byte to UTF-8.
decode [256]utf8Enc
// encoding is the map from runes to encoded bytes. Each entry is a
// uint32: the high 8 bits are the encoded byte and the low 24 bits are
// the rune. The table entries are sorted by ascending rune.
encode [256]uint32
}
// NewDecoder implements the encoding.Encoding interface.
func (m *Charmap) NewDecoder() *encoding.Decoder {
return &encoding.Decoder{Transformer: charmapDecoder{charmap: m}}
}
// NewEncoder implements the encoding.Encoding interface.
func (m *Charmap) NewEncoder() *encoding.Encoder {
return &encoding.Encoder{Transformer: charmapEncoder{charmap: m}}
}
// String returns the Charmap's name.
func (m *Charmap) String() string {
return m.name
}
// ID implements an internal interface.
func (m *Charmap) ID() (mib identifier.MIB, other string) {
return m.mib, ""
}
// charmapDecoder implements transform.Transformer by decoding to UTF-8.
type charmapDecoder struct {
transform.NopResetter
charmap *Charmap
}
func (m charmapDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
for i, c := range src {
if m.charmap.asciiSuperset && c < utf8.RuneSelf {
if nDst >= len(dst) {
err = transform.ErrShortDst
break
}
dst[nDst] = c
nDst++
nSrc = i + 1
continue
}
decode := &m.charmap.decode[c]
n := int(decode.len)
if nDst+n > len(dst) {
err = transform.ErrShortDst
break
}
// It's 15% faster to avoid calling copy for these tiny slices.
for j := 0; j < n; j++ {
dst[nDst] = decode.data[j]
nDst++
}
nSrc = i + 1
}
return nDst, nSrc, err
}
// DecodeByte returns the Charmap's rune decoding of the byte b.
func (m *Charmap) DecodeByte(b byte) rune {
switch x := &m.decode[b]; x.len {
case 1:
return rune(x.data[0])
case 2:
return rune(x.data[0]&0x1f)<<6 | rune(x.data[1]&0x3f)
default:
return rune(x.data[0]&0x0f)<<12 | rune(x.data[1]&0x3f)<<6 | rune(x.data[2]&0x3f)
}
}
// charmapEncoder implements transform.Transformer by encoding from UTF-8.
type charmapEncoder struct {
transform.NopResetter
charmap *Charmap
}
func (m charmapEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
r, size := rune(0), 0
loop:
for nSrc < len(src) {
if nDst >= len(dst) {
err = transform.ErrShortDst
break
}
r = rune(src[nSrc])
// Decode a 1-byte rune.
if r < utf8.RuneSelf {
if m.charmap.asciiSuperset {
nSrc++
dst[nDst] = uint8(r)
nDst++
continue
}
size = 1
} else {
// Decode a multi-byte rune.
r, size = utf8.DecodeRune(src[nSrc:])
if size == 1 {
// All valid runes of size 1 (those below utf8.RuneSelf) were
// handled above. We have invalid UTF-8 or we haven't seen the
// full character yet.
if !atEOF && !utf8.FullRune(src[nSrc:]) {
err = transform.ErrShortSrc
} else {
err = internal.RepertoireError(m.charmap.replacement)
}
break
}
}
// Binary search in [low, high) for that rune in the m.charmap.encode table.
for low, high := int(m.charmap.low), 0x100; ; {
if low >= high {
err = internal.RepertoireError(m.charmap.replacement)
break loop
}
mid := (low + high) / 2
got := m.charmap.encode[mid]
gotRune := rune(got & (1<<24 - 1))
if gotRune < r {
low = mid + 1
} else if gotRune > r {
high = mid
} else {
dst[nDst] = byte(got >> 24)
nDst++
break
}
}
nSrc += size
}
return nDst, nSrc, err
}
// EncodeRune returns the Charmap's byte encoding of the rune r. ok is whether
// r is in the Charmap's repertoire. If not, b is set to the Charmap's
// replacement byte. This is often the ASCII substitute character '\x1a'.
func (m *Charmap) EncodeRune(r rune) (b byte, ok bool) {
if r < utf8.RuneSelf && m.asciiSuperset {
return byte(r), true
}
for low, high := int(m.low), 0x100; ; {
if low >= high {
return m.replacement, false
}
mid := (low + high) / 2
got := m.encode[mid]
gotRune := rune(got & (1<<24 - 1))
if gotRune < r {
low = mid + 1
} else if gotRune > r {
high = mid
} else {
return byte(got >> 24), true
}
}
}
File diff suppressed because it is too large Load Diff
+335
View File
@@ -0,0 +1,335 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package encoding defines an interface for character encodings, such as Shift
// JIS and Windows 1252, that can convert to and from UTF-8.
//
// Encoding implementations are provided in other packages, such as
// golang.org/x/text/encoding/charmap and
// golang.org/x/text/encoding/japanese.
package encoding // import "golang.org/x/text/encoding"
import (
"errors"
"io"
"strconv"
"unicode/utf8"
"golang.org/x/text/encoding/internal/identifier"
"golang.org/x/text/transform"
)
// TODO:
// - There seems to be some inconsistency in when decoders return errors
// and when not. Also documentation seems to suggest they shouldn't return
// errors at all (except for UTF-16).
// - Encoders seem to rely on or at least benefit from the input being in NFC
// normal form. Perhaps add an example how users could prepare their output.
// Encoding is a character set encoding that can be transformed to and from
// UTF-8.
type Encoding interface {
// NewDecoder returns a Decoder.
NewDecoder() *Decoder
// NewEncoder returns an Encoder.
NewEncoder() *Encoder
}
// A Decoder converts bytes to UTF-8. It implements transform.Transformer.
//
// Transforming source bytes that are not of that encoding will not result in an
// error per se. Each byte that cannot be transcoded will be represented in the
// output by the UTF-8 encoding of '\uFFFD', the replacement rune.
type Decoder struct {
transform.Transformer
// This forces external creators of Decoders to use names in struct
// initializers, allowing for future extendibility without having to break
// code.
_ struct{}
}
// Bytes converts the given encoded bytes to UTF-8. It returns the converted
// bytes or nil, err if any error occurred.
func (d *Decoder) Bytes(b []byte) ([]byte, error) {
b, _, err := transform.Bytes(d, b)
if err != nil {
return nil, err
}
return b, nil
}
// String converts the given encoded string to UTF-8. It returns the converted
// string or "", err if any error occurred.
func (d *Decoder) String(s string) (string, error) {
s, _, err := transform.String(d, s)
if err != nil {
return "", err
}
return s, nil
}
// Reader wraps another Reader to decode its bytes.
//
// The Decoder may not be used for any other operation as long as the returned
// Reader is in use.
func (d *Decoder) Reader(r io.Reader) io.Reader {
return transform.NewReader(r, d)
}
// An Encoder converts bytes from UTF-8. It implements transform.Transformer.
//
// Each rune that cannot be transcoded will result in an error. In this case,
// the transform will consume all source byte up to, not including the offending
// rune. Transforming source bytes that are not valid UTF-8 will be replaced by
// `\uFFFD`. To return early with an error instead, use transform.Chain to
// preprocess the data with a UTF8Validator.
type Encoder struct {
transform.Transformer
// This forces external creators of Encoders to use names in struct
// initializers, allowing for future extendibility without having to break
// code.
_ struct{}
}
// Bytes converts bytes from UTF-8. It returns the converted bytes or nil, err if
// any error occurred.
func (e *Encoder) Bytes(b []byte) ([]byte, error) {
b, _, err := transform.Bytes(e, b)
if err != nil {
return nil, err
}
return b, nil
}
// String converts a string from UTF-8. It returns the converted string or
// "", err if any error occurred.
func (e *Encoder) String(s string) (string, error) {
s, _, err := transform.String(e, s)
if err != nil {
return "", err
}
return s, nil
}
// Writer wraps another Writer to encode its UTF-8 output.
//
// The Encoder may not be used for any other operation as long as the returned
// Writer is in use.
func (e *Encoder) Writer(w io.Writer) io.Writer {
return transform.NewWriter(w, e)
}
// ASCIISub is the ASCII substitute character, as recommended by
// https://unicode.org/reports/tr36/#Text_Comparison
const ASCIISub = '\x1a'
// Nop is the nop encoding. Its transformed bytes are the same as the source
// bytes; it does not replace invalid UTF-8 sequences.
var Nop Encoding = nop{}
type nop struct{}
func (nop) NewDecoder() *Decoder {
return &Decoder{Transformer: transform.Nop}
}
func (nop) NewEncoder() *Encoder {
return &Encoder{Transformer: transform.Nop}
}
// Replacement is the replacement encoding. Decoding from the replacement
// encoding yields a single '\uFFFD' replacement rune. Encoding from UTF-8 to
// the replacement encoding yields the same as the source bytes except that
// invalid UTF-8 is converted to '\uFFFD'.
//
// It is defined at http://encoding.spec.whatwg.org/#replacement
var Replacement Encoding = replacement{}
type replacement struct{}
func (replacement) NewDecoder() *Decoder {
return &Decoder{Transformer: replacementDecoder{}}
}
func (replacement) NewEncoder() *Encoder {
return &Encoder{Transformer: replacementEncoder{}}
}
func (replacement) ID() (mib identifier.MIB, other string) {
return identifier.Replacement, ""
}
type replacementDecoder struct{ transform.NopResetter }
func (replacementDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
if len(dst) < 3 {
return 0, 0, transform.ErrShortDst
}
if atEOF {
const fffd = "\ufffd"
dst[0] = fffd[0]
dst[1] = fffd[1]
dst[2] = fffd[2]
nDst = 3
}
return nDst, len(src), nil
}
type replacementEncoder struct{ transform.NopResetter }
func (replacementEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
r, size := rune(0), 0
for ; nSrc < len(src); nSrc += size {
r = rune(src[nSrc])
// Decode a 1-byte rune.
if r < utf8.RuneSelf {
size = 1
} else {
// Decode a multi-byte rune.
r, size = utf8.DecodeRune(src[nSrc:])
if size == 1 {
// All valid runes of size 1 (those below utf8.RuneSelf) were
// handled above. We have invalid UTF-8 or we haven't seen the
// full character yet.
if !atEOF && !utf8.FullRune(src[nSrc:]) {
err = transform.ErrShortSrc
break
}
r = '\ufffd'
}
}
if nDst+utf8.RuneLen(r) > len(dst) {
err = transform.ErrShortDst
break
}
nDst += utf8.EncodeRune(dst[nDst:], r)
}
return nDst, nSrc, err
}
// HTMLEscapeUnsupported wraps encoders to replace source runes outside the
// repertoire of the destination encoding with HTML escape sequences.
//
// This wrapper exists to comply to URL and HTML forms requiring a
// non-terminating legacy encoder. The produced sequences may lead to data
// loss as they are indistinguishable from legitimate input. To avoid this
// issue, use UTF-8 encodings whenever possible.
func HTMLEscapeUnsupported(e *Encoder) *Encoder {
return &Encoder{Transformer: &errorHandler{e, errorToHTML}}
}
// ReplaceUnsupported wraps encoders to replace source runes outside the
// repertoire of the destination encoding with an encoding-specific
// replacement.
//
// This wrapper is only provided for backwards compatibility and legacy
// handling. Its use is strongly discouraged. Use UTF-8 whenever possible.
func ReplaceUnsupported(e *Encoder) *Encoder {
return &Encoder{Transformer: &errorHandler{e, errorToReplacement}}
}
type errorHandler struct {
*Encoder
handler func(dst []byte, r rune, err repertoireError) (n int, ok bool)
}
// TODO: consider making this error public in some form.
type repertoireError interface {
Replacement() byte
}
func (h errorHandler) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
nDst, nSrc, err = h.Transformer.Transform(dst, src, atEOF)
for err != nil {
rerr, ok := err.(repertoireError)
if !ok {
return nDst, nSrc, err
}
r, sz := utf8.DecodeRune(src[nSrc:])
n, ok := h.handler(dst[nDst:], r, rerr)
if !ok {
return nDst, nSrc, transform.ErrShortDst
}
err = nil
nDst += n
if nSrc += sz; nSrc < len(src) {
var dn, sn int
dn, sn, err = h.Transformer.Transform(dst[nDst:], src[nSrc:], atEOF)
nDst += dn
nSrc += sn
}
}
return nDst, nSrc, err
}
func errorToHTML(dst []byte, r rune, err repertoireError) (n int, ok bool) {
buf := [8]byte{}
b := strconv.AppendUint(buf[:0], uint64(r), 10)
if n = len(b) + len("&#;"); n >= len(dst) {
return 0, false
}
dst[0] = '&'
dst[1] = '#'
dst[copy(dst[2:], b)+2] = ';'
return n, true
}
func errorToReplacement(dst []byte, r rune, err repertoireError) (n int, ok bool) {
if len(dst) == 0 {
return 0, false
}
dst[0] = err.Replacement()
return 1, true
}
// ErrInvalidUTF8 means that a transformer encountered invalid UTF-8.
var ErrInvalidUTF8 = errors.New("encoding: invalid UTF-8")
// UTF8Validator is a transformer that returns ErrInvalidUTF8 on the first
// input byte that is not valid UTF-8.
var UTF8Validator transform.Transformer = utf8Validator{}
type utf8Validator struct{ transform.NopResetter }
func (utf8Validator) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
n := len(src)
if n > len(dst) {
n = len(dst)
}
for i := 0; i < n; {
if c := src[i]; c < utf8.RuneSelf {
dst[i] = c
i++
continue
}
_, size := utf8.DecodeRune(src[i:])
if size == 1 {
// All valid runes of size 1 (those below utf8.RuneSelf) were
// handled above. We have invalid UTF-8 or we haven't seen the
// full character yet.
err = ErrInvalidUTF8
if !atEOF && !utf8.FullRune(src[i:]) {
err = transform.ErrShortSrc
}
return i, i, err
}
if i+size > len(dst) {
return i, i, transform.ErrShortDst
}
for ; size > 0; size-- {
dst[i] = src[i]
i++
}
}
if len(src) > len(dst) {
err = transform.ErrShortDst
}
return n, n, err
}
+74
View File
@@ -0,0 +1,74 @@
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ianaindex
import (
"unicode"
"unicode/utf8"
"golang.org/x/text/encoding"
"golang.org/x/text/encoding/internal"
"golang.org/x/text/encoding/internal/identifier"
"golang.org/x/text/transform"
)
type asciiDecoder struct {
transform.NopResetter
}
func (d asciiDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
for _, c := range src {
if c > unicode.MaxASCII {
r := unicode.ReplacementChar
if nDst+utf8.RuneLen(r) > len(dst) {
err = transform.ErrShortDst
break
}
nDst += utf8.EncodeRune(dst[nDst:], r)
nSrc++
continue
}
if nDst >= len(dst) {
err = transform.ErrShortDst
break
}
dst[nDst] = c
nDst++
nSrc++
}
return nDst, nSrc, err
}
type asciiEncoder struct {
transform.NopResetter
}
func (d asciiEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
for _, c := range src {
if c > unicode.MaxASCII {
err = internal.RepertoireError(encoding.ASCIISub)
break
}
if nDst >= len(dst) {
err = transform.ErrShortDst
break
}
dst[nDst] = c
nDst++
nSrc++
}
return nDst, nSrc, err
}
var asciiEnc = &internal.Encoding{
Encoding: &internal.SimpleEncoding{
asciiDecoder{},
asciiEncoder{},
},
Name: "US-ASCII",
MIB: identifier.ASCII,
}
+214
View File
@@ -0,0 +1,214 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:generate go run gen.go
// Package ianaindex maps names to Encodings as specified by the IANA registry.
// This includes both the MIME and IANA names.
//
// See http://www.iana.org/assignments/character-sets/character-sets.xhtml for
// more details.
package ianaindex
import (
"errors"
"sort"
"strings"
"golang.org/x/text/encoding"
"golang.org/x/text/encoding/charmap"
"golang.org/x/text/encoding/internal/identifier"
"golang.org/x/text/encoding/japanese"
"golang.org/x/text/encoding/korean"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/encoding/traditionalchinese"
"golang.org/x/text/encoding/unicode"
)
// TODO: remove the "Status... incomplete" in the package doc comment.
// TODO: allow users to specify their own aliases?
// TODO: allow users to specify their own indexes?
// TODO: allow canonicalizing names
// NOTE: only use these top-level variables if we can get the linker to drop
// the indexes when they are not used. Make them a function or perhaps only
// support MIME otherwise.
var (
// MIME is an index to map MIME names.
MIME *Index = mime
// IANA is an index that supports all names and aliases using IANA names as
// the canonical identifier.
IANA *Index = iana
// MIB is an index that associates the MIB display name with an Encoding.
MIB *Index = mib
mime = &Index{mimeName, ianaToMIB, ianaAliases, encodings[:]}
iana = &Index{ianaName, ianaToMIB, ianaAliases, encodings[:]}
mib = &Index{mibName, ianaToMIB, ianaAliases, encodings[:]}
)
// Index maps names registered by IANA to Encodings.
// Currently different Indexes only differ in the names they return for
// encodings. In the future they may also differ in supported aliases.
type Index struct {
names func(i int) string
toMIB []identifier.MIB // Sorted slice of supported MIBs
alias map[string]int
enc []encoding.Encoding
}
var (
errInvalidName = errors.New("ianaindex: invalid encoding name")
errUnknown = errors.New("ianaindex: unknown Encoding")
errUnsupported = errors.New("ianaindex: unsupported Encoding")
)
// Encoding returns an Encoding for IANA-registered names. Matching is
// case-insensitive.
//
// If the provided name doesn't match a IANA-registered charset, an error is
// returned. If the name matches a IANA-registered charset but isn't supported,
// a nil encoding and a nil error are returned.
func (x *Index) Encoding(name string) (encoding.Encoding, error) {
name = strings.TrimSpace(name)
// First try without lowercasing (possibly creating an allocation).
i, ok := x.alias[name]
if !ok {
i, ok = x.alias[strings.ToLower(name)]
if !ok {
return nil, errInvalidName
}
}
return x.enc[i], nil
}
// Name reports the canonical name of the given Encoding. It will return an
// error if the e is not associated with a known encoding scheme.
func (x *Index) Name(e encoding.Encoding) (string, error) {
id, ok := e.(identifier.Interface)
if !ok {
return "", errUnknown
}
mib, _ := id.ID()
if mib == 0 {
return "", errUnknown
}
v := findMIB(x.toMIB, mib)
if v == -1 {
return "", errUnsupported
}
return x.names(v), nil
}
// TODO: the coverage of this index is rather spotty. Allowing users to set
// encodings would allow:
// - users to increase coverage
// - allow a partially loaded set of encodings in case the user doesn't need to
// them all.
// - write an OS-specific wrapper for supported encodings and set them.
// The exact definition of Set depends a bit on if and how we want to let users
// write their own Encoding implementations. Also, it is not possible yet to
// only partially load the encodings without doing some refactoring. Until this
// is solved, we might as well not support Set.
// // Set sets the e to be used for the encoding scheme identified by name. Only
// // canonical names may be used. An empty name assigns e to its internally
// // associated encoding scheme.
// func (x *Index) Set(name string, e encoding.Encoding) error {
// panic("TODO: implement")
// }
func findMIB(x []identifier.MIB, mib identifier.MIB) int {
i := sort.Search(len(x), func(i int) bool { return x[i] >= mib })
if i < len(x) && x[i] == mib {
return i
}
return -1
}
const maxMIMENameLen = '0' - 1 // officially 40, but we leave some buffer.
func mimeName(x int) string {
n := ianaNames[x]
// See gen.go for a description of the encoding.
if n[0] <= maxMIMENameLen {
return n[1:n[0]]
}
return n
}
func ianaName(x int) string {
n := ianaNames[x]
// See gen.go for a description of the encoding.
if n[0] <= maxMIMENameLen {
return n[n[0]:]
}
return n
}
func mibName(x int) string {
return mibNames[x]
}
var encodings = [numIANA]encoding.Encoding{
enc3: asciiEnc,
enc106: unicode.UTF8,
enc1015: unicode.UTF16(unicode.BigEndian, unicode.UseBOM),
enc1013: unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM),
enc1014: unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM),
enc2028: charmap.CodePage037,
enc2011: charmap.CodePage437,
enc2009: charmap.CodePage850,
enc2010: charmap.CodePage852,
enc2046: charmap.CodePage855,
enc2089: charmap.CodePage858,
enc2048: charmap.CodePage860,
enc2013: charmap.CodePage862,
enc2050: charmap.CodePage863,
enc2052: charmap.CodePage865,
enc2086: charmap.CodePage866,
enc2102: charmap.CodePage1047,
enc2091: charmap.CodePage1140,
enc4: charmap.ISO8859_1,
enc5: charmap.ISO8859_2,
enc6: charmap.ISO8859_3,
enc7: charmap.ISO8859_4,
enc8: charmap.ISO8859_5,
enc9: charmap.ISO8859_6,
enc81: charmap.ISO8859_6E,
enc82: charmap.ISO8859_6I,
enc10: charmap.ISO8859_7,
enc11: charmap.ISO8859_8,
enc84: charmap.ISO8859_8E,
enc85: charmap.ISO8859_8I,
enc12: charmap.ISO8859_9,
enc13: charmap.ISO8859_10,
enc109: charmap.ISO8859_13,
enc110: charmap.ISO8859_14,
enc111: charmap.ISO8859_15,
enc112: charmap.ISO8859_16,
enc2084: charmap.KOI8R,
enc2088: charmap.KOI8U,
enc2027: charmap.Macintosh,
enc2109: charmap.Windows874,
enc2250: charmap.Windows1250,
enc2251: charmap.Windows1251,
enc2252: charmap.Windows1252,
enc2253: charmap.Windows1253,
enc2254: charmap.Windows1254,
enc2255: charmap.Windows1255,
enc2256: charmap.Windows1256,
enc2257: charmap.Windows1257,
enc2258: charmap.Windows1258,
enc18: japanese.EUCJP,
enc39: japanese.ISO2022JP,
enc17: japanese.ShiftJIS,
enc38: korean.EUCKR,
enc114: simplifiedchinese.GB18030,
enc113: simplifiedchinese.GBK,
enc2085: simplifiedchinese.HZGB2312,
enc2026: traditionalchinese.Big5,
}
File diff suppressed because it is too large Load Diff
+81
View File
@@ -0,0 +1,81 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:generate go run gen.go
// Package identifier defines the contract between implementations of Encoding
// and Index by defining identifiers that uniquely identify standardized coded
// character sets (CCS) and character encoding schemes (CES), which we will
// together refer to as encodings, for which Encoding implementations provide
// converters to and from UTF-8. This package is typically only of concern to
// implementers of Indexes and Encodings.
//
// One part of the identifier is the MIB code, which is defined by IANA and
// uniquely identifies a CCS or CES. Each code is associated with data that
// references authorities, official documentation as well as aliases and MIME
// names.
//
// Not all CESs are covered by the IANA registry. The "other" string that is
// returned by ID can be used to identify other character sets or versions of
// existing ones.
//
// It is recommended that each package that provides a set of Encodings provide
// the All and Common variables to reference all supported encodings and
// commonly used subset. This allows Index implementations to include all
// available encodings without explicitly referencing or knowing about them.
package identifier
// Note: this package is internal, but could be made public if there is a need
// for writing third-party Indexes and Encodings.
// References:
// - http://source.icu-project.org/repos/icu/icu/trunk/source/data/mappings/convrtrs.txt
// - http://www.iana.org/assignments/character-sets/character-sets.xhtml
// - http://www.iana.org/assignments/ianacharset-mib/ianacharset-mib
// - http://www.ietf.org/rfc/rfc2978.txt
// - https://www.unicode.org/reports/tr22/
// - http://www.w3.org/TR/encoding/
// - https://encoding.spec.whatwg.org/
// - https://encoding.spec.whatwg.org/encodings.json
// - https://tools.ietf.org/html/rfc6657#section-5
// Interface can be implemented by Encodings to define the CCS or CES for which
// it implements conversions.
type Interface interface {
// ID returns an encoding identifier. Exactly one of the mib and other
// values should be non-zero.
//
// In the usual case it is only necessary to indicate the MIB code. The
// other string can be used to specify encodings for which there is no MIB,
// such as "x-mac-dingbat".
//
// The other string may only contain the characters a-z, A-Z, 0-9, - and _.
ID() (mib MIB, other string)
// NOTE: the restrictions on the encoding are to allow extending the syntax
// with additional information such as versions, vendors and other variants.
}
// A MIB identifies an encoding. It is derived from the IANA MIB codes and adds
// some identifiers for some encodings that are not covered by the IANA
// standard.
//
// See http://www.iana.org/assignments/ianacharset-mib.
type MIB uint16
// These additional MIB types are not defined in IANA. They are added because
// they are common and defined within the text repo.
const (
// Unofficial marks the start of encodings not registered by IANA.
Unofficial MIB = 10000 + iota
// Replacement is the WhatWG replacement encoding.
Replacement
// XUserDefined is the code for x-user-defined.
XUserDefined
// MacintoshCyrillic is the code for x-mac-cyrillic.
MacintoshCyrillic
)
File diff suppressed because it is too large Load Diff
+75
View File
@@ -0,0 +1,75 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package internal contains code that is shared among encoding implementations.
package internal
import (
"golang.org/x/text/encoding"
"golang.org/x/text/encoding/internal/identifier"
"golang.org/x/text/transform"
)
// Encoding is an implementation of the Encoding interface that adds the String
// and ID methods to an existing encoding.
type Encoding struct {
encoding.Encoding
Name string
MIB identifier.MIB
}
// _ verifies that Encoding implements identifier.Interface.
var _ identifier.Interface = (*Encoding)(nil)
func (e *Encoding) String() string {
return e.Name
}
func (e *Encoding) ID() (mib identifier.MIB, other string) {
return e.MIB, ""
}
// SimpleEncoding is an Encoding that combines two Transformers.
type SimpleEncoding struct {
Decoder transform.Transformer
Encoder transform.Transformer
}
func (e *SimpleEncoding) NewDecoder() *encoding.Decoder {
return &encoding.Decoder{Transformer: e.Decoder}
}
func (e *SimpleEncoding) NewEncoder() *encoding.Encoder {
return &encoding.Encoder{Transformer: e.Encoder}
}
// FuncEncoding is an Encoding that combines two functions returning a new
// Transformer.
type FuncEncoding struct {
Decoder func() transform.Transformer
Encoder func() transform.Transformer
}
func (e FuncEncoding) NewDecoder() *encoding.Decoder {
return &encoding.Decoder{Transformer: e.Decoder()}
}
func (e FuncEncoding) NewEncoder() *encoding.Encoder {
return &encoding.Encoder{Transformer: e.Encoder()}
}
// A RepertoireError indicates a rune is not in the repertoire of a destination
// encoding. It is associated with an encoding-specific suggested replacement
// byte.
type RepertoireError byte
// Error implements the error interrface.
func (r RepertoireError) Error() string {
return "encoding: rune not supported by encoding."
}
// Replacement returns the replacement string associated with this error.
func (r RepertoireError) Replacement() byte { return byte(r) }
var ErrASCIIReplacement = RepertoireError(encoding.ASCIISub)
+12
View File
@@ -0,0 +1,12 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package japanese
import (
"golang.org/x/text/encoding"
)
// All is a list of all defined encodings in this package.
var All = []encoding.Encoding{EUCJP, ISO2022JP, ShiftJIS}
+225
View File
@@ -0,0 +1,225 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package japanese
import (
"unicode/utf8"
"golang.org/x/text/encoding"
"golang.org/x/text/encoding/internal"
"golang.org/x/text/encoding/internal/identifier"
"golang.org/x/text/transform"
)
// EUCJP is the EUC-JP encoding.
var EUCJP encoding.Encoding = &eucJP
var eucJP = internal.Encoding{
&internal.SimpleEncoding{eucJPDecoder{}, eucJPEncoder{}},
"EUC-JP",
identifier.EUCPkdFmtJapanese,
}
type eucJPDecoder struct{ transform.NopResetter }
// See https://encoding.spec.whatwg.org/#euc-jp-decoder.
func (eucJPDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
r, size := rune(0), 0
loop:
for ; nSrc < len(src); nSrc += size {
switch c0 := src[nSrc]; {
case c0 < utf8.RuneSelf:
r, size = rune(c0), 1
case c0 == 0x8e:
if nSrc+1 >= len(src) {
if !atEOF {
err = transform.ErrShortSrc
break loop
}
r, size = utf8.RuneError, 1
break
}
c1 := src[nSrc+1]
switch {
case c1 < 0xa1:
r, size = utf8.RuneError, 1
case c1 > 0xdf:
r, size = utf8.RuneError, 2
if c1 == 0xff {
size = 1
}
default:
r, size = rune(c1)+(0xff61-0xa1), 2
}
case c0 == 0x8f:
if nSrc+2 >= len(src) {
if !atEOF {
err = transform.ErrShortSrc
break loop
}
r, size = utf8.RuneError, 1
if p := nSrc + 1; p < len(src) && 0xa1 <= src[p] && src[p] < 0xfe {
size = 2
}
break
}
c1 := src[nSrc+1]
if c1 < 0xa1 || 0xfe < c1 {
r, size = utf8.RuneError, 1
break
}
c2 := src[nSrc+2]
if c2 < 0xa1 || 0xfe < c2 {
r, size = utf8.RuneError, 2
break
}
r, size = utf8.RuneError, 3
if i := int(c1-0xa1)*94 + int(c2-0xa1); i < len(jis0212Decode) {
r = rune(jis0212Decode[i])
if r == 0 {
r = utf8.RuneError
}
}
case 0xa1 <= c0 && c0 <= 0xfe:
if nSrc+1 >= len(src) {
if !atEOF {
err = transform.ErrShortSrc
break loop
}
r, size = utf8.RuneError, 1
break
}
c1 := src[nSrc+1]
if c1 < 0xa1 || 0xfe < c1 {
r, size = utf8.RuneError, 1
break
}
r, size = utf8.RuneError, 2
if i := int(c0-0xa1)*94 + int(c1-0xa1); i < len(jis0208Decode) {
r = rune(jis0208Decode[i])
if r == 0 {
r = utf8.RuneError
}
}
default:
r, size = utf8.RuneError, 1
}
if nDst+utf8.RuneLen(r) > len(dst) {
err = transform.ErrShortDst
break loop
}
nDst += utf8.EncodeRune(dst[nDst:], r)
}
return nDst, nSrc, err
}
type eucJPEncoder struct{ transform.NopResetter }
func (eucJPEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
r, size := rune(0), 0
for ; nSrc < len(src); nSrc += size {
r = rune(src[nSrc])
// Decode a 1-byte rune.
if r < utf8.RuneSelf {
size = 1
} else {
// Decode a multi-byte rune.
r, size = utf8.DecodeRune(src[nSrc:])
if size == 1 {
// All valid runes of size 1 (those below utf8.RuneSelf) were
// handled above. We have invalid UTF-8 or we haven't seen the
// full character yet.
if !atEOF && !utf8.FullRune(src[nSrc:]) {
err = transform.ErrShortSrc
break
}
}
// func init checks that the switch covers all tables.
switch {
case encode0Low <= r && r < encode0High:
if r = rune(encode0[r-encode0Low]); r != 0 {
goto write2or3
}
case encode1Low <= r && r < encode1High:
if r = rune(encode1[r-encode1Low]); r != 0 {
goto write2or3
}
case encode2Low <= r && r < encode2High:
if r = rune(encode2[r-encode2Low]); r != 0 {
goto write2or3
}
case encode3Low <= r && r < encode3High:
if r = rune(encode3[r-encode3Low]); r != 0 {
goto write2or3
}
case encode4Low <= r && r < encode4High:
if r = rune(encode4[r-encode4Low]); r != 0 {
goto write2or3
}
case encode5Low <= r && r < encode5High:
if 0xff61 <= r && r < 0xffa0 {
goto write2
}
if r = rune(encode5[r-encode5Low]); r != 0 {
goto write2or3
}
}
err = internal.ErrASCIIReplacement
break
}
if nDst >= len(dst) {
err = transform.ErrShortDst
break
}
dst[nDst] = uint8(r)
nDst++
continue
write2or3:
if r>>tableShift == jis0208 {
if nDst+2 > len(dst) {
err = transform.ErrShortDst
break
}
} else {
if nDst+3 > len(dst) {
err = transform.ErrShortDst
break
}
dst[nDst] = 0x8f
nDst++
}
dst[nDst+0] = 0xa1 + uint8(r>>codeShift)&codeMask
dst[nDst+1] = 0xa1 + uint8(r)&codeMask
nDst += 2
continue
write2:
if nDst+2 > len(dst) {
err = transform.ErrShortDst
break
}
dst[nDst+0] = 0x8e
dst[nDst+1] = uint8(r - (0xff61 - 0xa1))
nDst += 2
continue
}
return nDst, nSrc, err
}
func init() {
// Check that the hard-coded encode switch covers all tables.
if numEncodeTables != 6 {
panic("bad numEncodeTables")
}
}
+299
View File
@@ -0,0 +1,299 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package japanese
import (
"unicode/utf8"
"golang.org/x/text/encoding"
"golang.org/x/text/encoding/internal"
"golang.org/x/text/encoding/internal/identifier"
"golang.org/x/text/transform"
)
// ISO2022JP is the ISO-2022-JP encoding.
var ISO2022JP encoding.Encoding = &iso2022JP
var iso2022JP = internal.Encoding{
internal.FuncEncoding{iso2022JPNewDecoder, iso2022JPNewEncoder},
"ISO-2022-JP",
identifier.ISO2022JP,
}
func iso2022JPNewDecoder() transform.Transformer {
return new(iso2022JPDecoder)
}
func iso2022JPNewEncoder() transform.Transformer {
return new(iso2022JPEncoder)
}
const (
asciiState = iota
katakanaState
jis0208State
jis0212State
)
const asciiEsc = 0x1b
type iso2022JPDecoder int
func (d *iso2022JPDecoder) Reset() {
*d = asciiState
}
func (d *iso2022JPDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
r, size := rune(0), 0
for ; nSrc < len(src); nSrc += size {
c0 := src[nSrc]
if c0 >= utf8.RuneSelf {
r, size = '\ufffd', 1
goto write
}
if c0 == asciiEsc {
if nSrc+2 >= len(src) {
if !atEOF {
return nDst, nSrc, transform.ErrShortSrc
}
// TODO: is it correct to only skip 1??
r, size = '\ufffd', 1
goto write
}
size = 3
c1 := src[nSrc+1]
c2 := src[nSrc+2]
switch {
case c1 == '$' && (c2 == '@' || c2 == 'B'): // 0x24 {0x40, 0x42}
*d = jis0208State
continue
case c1 == '$' && c2 == '(': // 0x24 0x28
if nSrc+3 >= len(src) {
if !atEOF {
return nDst, nSrc, transform.ErrShortSrc
}
r, size = '\ufffd', 1
goto write
}
size = 4
if src[nSrc+3] == 'D' {
*d = jis0212State
continue
}
case c1 == '(' && (c2 == 'B' || c2 == 'J'): // 0x28 {0x42, 0x4A}
*d = asciiState
continue
case c1 == '(' && c2 == 'I': // 0x28 0x49
*d = katakanaState
continue
}
r, size = '\ufffd', 1
goto write
}
switch *d {
case asciiState:
r, size = rune(c0), 1
case katakanaState:
if c0 < 0x21 || 0x60 <= c0 {
r, size = '\ufffd', 1
goto write
}
r, size = rune(c0)+(0xff61-0x21), 1
default:
if c0 == 0x0a {
*d = asciiState
r, size = rune(c0), 1
goto write
}
if nSrc+1 >= len(src) {
if !atEOF {
return nDst, nSrc, transform.ErrShortSrc
}
r, size = '\ufffd', 1
goto write
}
size = 2
c1 := src[nSrc+1]
i := int(c0-0x21)*94 + int(c1-0x21)
if *d == jis0208State && i < len(jis0208Decode) {
r = rune(jis0208Decode[i])
} else if *d == jis0212State && i < len(jis0212Decode) {
r = rune(jis0212Decode[i])
} else {
r = '\ufffd'
goto write
}
if r == 0 {
r = '\ufffd'
}
}
write:
if nDst+utf8.RuneLen(r) > len(dst) {
return nDst, nSrc, transform.ErrShortDst
}
nDst += utf8.EncodeRune(dst[nDst:], r)
}
return nDst, nSrc, err
}
type iso2022JPEncoder int
func (e *iso2022JPEncoder) Reset() {
*e = asciiState
}
func (e *iso2022JPEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
r, size := rune(0), 0
for ; nSrc < len(src); nSrc += size {
r = rune(src[nSrc])
// Decode a 1-byte rune.
if r < utf8.RuneSelf {
size = 1
} else {
// Decode a multi-byte rune.
r, size = utf8.DecodeRune(src[nSrc:])
if size == 1 {
// All valid runes of size 1 (those below utf8.RuneSelf) were
// handled above. We have invalid UTF-8 or we haven't seen the
// full character yet.
if !atEOF && !utf8.FullRune(src[nSrc:]) {
err = transform.ErrShortSrc
break
}
}
// func init checks that the switch covers all tables.
//
// http://encoding.spec.whatwg.org/#iso-2022-jp says that "the index jis0212
// is not used by the iso-2022-jp encoder due to lack of widespread support".
//
// TODO: do we have to special-case U+00A5 and U+203E, as per
// http://encoding.spec.whatwg.org/#iso-2022-jp
// Doing so would mean that "\u00a5" would not be preserved
// after an encode-decode round trip.
switch {
case encode0Low <= r && r < encode0High:
if r = rune(encode0[r-encode0Low]); r>>tableShift == jis0208 {
goto writeJIS
}
case encode1Low <= r && r < encode1High:
if r = rune(encode1[r-encode1Low]); r>>tableShift == jis0208 {
goto writeJIS
}
case encode2Low <= r && r < encode2High:
if r = rune(encode2[r-encode2Low]); r>>tableShift == jis0208 {
goto writeJIS
}
case encode3Low <= r && r < encode3High:
if r = rune(encode3[r-encode3Low]); r>>tableShift == jis0208 {
goto writeJIS
}
case encode4Low <= r && r < encode4High:
if r = rune(encode4[r-encode4Low]); r>>tableShift == jis0208 {
goto writeJIS
}
case encode5Low <= r && r < encode5High:
if 0xff61 <= r && r < 0xffa0 {
goto writeKatakana
}
if r = rune(encode5[r-encode5Low]); r>>tableShift == jis0208 {
goto writeJIS
}
}
// Switch back to ASCII state in case of error so that an ASCII
// replacement character can be written in the correct state.
if *e != asciiState {
if nDst+3 > len(dst) {
err = transform.ErrShortDst
break
}
*e = asciiState
dst[nDst+0] = asciiEsc
dst[nDst+1] = '('
dst[nDst+2] = 'B'
nDst += 3
}
err = internal.ErrASCIIReplacement
break
}
if *e != asciiState {
if nDst+4 > len(dst) {
err = transform.ErrShortDst
break
}
*e = asciiState
dst[nDst+0] = asciiEsc
dst[nDst+1] = '('
dst[nDst+2] = 'B'
nDst += 3
} else if nDst >= len(dst) {
err = transform.ErrShortDst
break
}
dst[nDst] = uint8(r)
nDst++
continue
writeJIS:
if *e != jis0208State {
if nDst+5 > len(dst) {
err = transform.ErrShortDst
break
}
*e = jis0208State
dst[nDst+0] = asciiEsc
dst[nDst+1] = '$'
dst[nDst+2] = 'B'
nDst += 3
} else if nDst+2 > len(dst) {
err = transform.ErrShortDst
break
}
dst[nDst+0] = 0x21 + uint8(r>>codeShift)&codeMask
dst[nDst+1] = 0x21 + uint8(r)&codeMask
nDst += 2
continue
writeKatakana:
if *e != katakanaState {
if nDst+4 > len(dst) {
err = transform.ErrShortDst
break
}
*e = katakanaState
dst[nDst+0] = asciiEsc
dst[nDst+1] = '('
dst[nDst+2] = 'I'
nDst += 3
} else if nDst >= len(dst) {
err = transform.ErrShortDst
break
}
dst[nDst] = uint8(r - (0xff61 - 0x21))
nDst++
continue
}
if atEOF && err == nil && *e != asciiState {
if nDst+3 > len(dst) {
err = transform.ErrShortDst
} else {
*e = asciiState
dst[nDst+0] = asciiEsc
dst[nDst+1] = '('
dst[nDst+2] = 'B'
nDst += 3
}
}
return nDst, nSrc, err
}
+189
View File
@@ -0,0 +1,189 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package japanese
import (
"unicode/utf8"
"golang.org/x/text/encoding"
"golang.org/x/text/encoding/internal"
"golang.org/x/text/encoding/internal/identifier"
"golang.org/x/text/transform"
)
// ShiftJIS is the Shift JIS encoding, also known as Code Page 932 and
// Windows-31J.
var ShiftJIS encoding.Encoding = &shiftJIS
var shiftJIS = internal.Encoding{
&internal.SimpleEncoding{shiftJISDecoder{}, shiftJISEncoder{}},
"Shift JIS",
identifier.ShiftJIS,
}
type shiftJISDecoder struct{ transform.NopResetter }
func (shiftJISDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
r, size := rune(0), 0
loop:
for ; nSrc < len(src); nSrc += size {
switch c0 := src[nSrc]; {
case c0 < utf8.RuneSelf:
r, size = rune(c0), 1
case 0xa1 <= c0 && c0 < 0xe0:
r, size = rune(c0)+(0xff61-0xa1), 1
case (0x81 <= c0 && c0 < 0xa0) || (0xe0 <= c0 && c0 < 0xfd):
if c0 <= 0x9f {
c0 -= 0x70
} else {
c0 -= 0xb0
}
c0 = 2*c0 - 0x21
if nSrc+1 >= len(src) {
if !atEOF {
err = transform.ErrShortSrc
break loop
}
r, size = '\ufffd', 1
goto write
}
c1 := src[nSrc+1]
switch {
case c1 < 0x40:
r, size = '\ufffd', 1 // c1 is ASCII so output on next round
goto write
case c1 < 0x7f:
c0--
c1 -= 0x40
case c1 == 0x7f:
r, size = '\ufffd', 1 // c1 is ASCII so output on next round
goto write
case c1 < 0x9f:
c0--
c1 -= 0x41
case c1 < 0xfd:
c1 -= 0x9f
default:
r, size = '\ufffd', 2
goto write
}
r, size = '\ufffd', 2
if i := int(c0)*94 + int(c1); i < len(jis0208Decode) {
r = rune(jis0208Decode[i])
if r == 0 {
r = '\ufffd'
}
}
case c0 == 0x80:
r, size = 0x80, 1
default:
r, size = '\ufffd', 1
}
write:
if nDst+utf8.RuneLen(r) > len(dst) {
err = transform.ErrShortDst
break loop
}
nDst += utf8.EncodeRune(dst[nDst:], r)
}
return nDst, nSrc, err
}
type shiftJISEncoder struct{ transform.NopResetter }
func (shiftJISEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
r, size := rune(0), 0
loop:
for ; nSrc < len(src); nSrc += size {
r = rune(src[nSrc])
// Decode a 1-byte rune.
if r < utf8.RuneSelf {
size = 1
} else {
// Decode a multi-byte rune.
r, size = utf8.DecodeRune(src[nSrc:])
if size == 1 {
// All valid runes of size 1 (those below utf8.RuneSelf) were
// handled above. We have invalid UTF-8 or we haven't seen the
// full character yet.
if !atEOF && !utf8.FullRune(src[nSrc:]) {
err = transform.ErrShortSrc
break loop
}
}
// func init checks that the switch covers all tables.
switch {
case encode0Low <= r && r < encode0High:
if r = rune(encode0[r-encode0Low]); r>>tableShift == jis0208 {
goto write2
}
case encode1Low <= r && r < encode1High:
if r = rune(encode1[r-encode1Low]); r>>tableShift == jis0208 {
goto write2
}
case encode2Low <= r && r < encode2High:
if r = rune(encode2[r-encode2Low]); r>>tableShift == jis0208 {
goto write2
}
case encode3Low <= r && r < encode3High:
if r = rune(encode3[r-encode3Low]); r>>tableShift == jis0208 {
goto write2
}
case encode4Low <= r && r < encode4High:
if r = rune(encode4[r-encode4Low]); r>>tableShift == jis0208 {
goto write2
}
case encode5Low <= r && r < encode5High:
if 0xff61 <= r && r < 0xffa0 {
r -= 0xff61 - 0xa1
goto write1
}
if r = rune(encode5[r-encode5Low]); r>>tableShift == jis0208 {
goto write2
}
}
err = internal.ErrASCIIReplacement
break
}
write1:
if nDst >= len(dst) {
err = transform.ErrShortDst
break
}
dst[nDst] = uint8(r)
nDst++
continue
write2:
j1 := uint8(r>>codeShift) & codeMask
j2 := uint8(r) & codeMask
if nDst+2 > len(dst) {
err = transform.ErrShortDst
break loop
}
if j1 <= 61 {
dst[nDst+0] = 129 + j1/2
} else {
dst[nDst+0] = 193 + j1/2
}
if j1&1 == 0 {
dst[nDst+1] = j2 + j2/63 + 64
} else {
dst[nDst+1] = j2 + 159
}
nDst += 2
continue
}
return nDst, nSrc, err
}
File diff suppressed because it is too large Load Diff
+177
View File
@@ -0,0 +1,177 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package korean
import (
"unicode/utf8"
"golang.org/x/text/encoding"
"golang.org/x/text/encoding/internal"
"golang.org/x/text/encoding/internal/identifier"
"golang.org/x/text/transform"
)
// All is a list of all defined encodings in this package.
var All = []encoding.Encoding{EUCKR}
// EUCKR is the EUC-KR encoding, also known as Code Page 949.
var EUCKR encoding.Encoding = &eucKR
var eucKR = internal.Encoding{
&internal.SimpleEncoding{eucKRDecoder{}, eucKREncoder{}},
"EUC-KR",
identifier.EUCKR,
}
type eucKRDecoder struct{ transform.NopResetter }
func (eucKRDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
r, size := rune(0), 0
loop:
for ; nSrc < len(src); nSrc += size {
switch c0 := src[nSrc]; {
case c0 < utf8.RuneSelf:
r, size = rune(c0), 1
case 0x81 <= c0 && c0 < 0xff:
if nSrc+1 >= len(src) {
if !atEOF {
err = transform.ErrShortSrc
break loop
}
r, size = utf8.RuneError, 1
break
}
c1 := src[nSrc+1]
size = 2
if c0 < 0xc7 {
r = 178 * rune(c0-0x81)
switch {
case 0x41 <= c1 && c1 < 0x5b:
r += rune(c1) - (0x41 - 0*26)
case 0x61 <= c1 && c1 < 0x7b:
r += rune(c1) - (0x61 - 1*26)
case 0x81 <= c1 && c1 < 0xff:
r += rune(c1) - (0x81 - 2*26)
default:
goto decError
}
} else if 0xa1 <= c1 && c1 < 0xff {
r = 178*(0xc7-0x81) + rune(c0-0xc7)*94 + rune(c1-0xa1)
} else {
goto decError
}
if int(r) < len(decode) {
r = rune(decode[r])
if r != 0 {
break
}
}
decError:
r = utf8.RuneError
if c1 < utf8.RuneSelf {
size = 1
}
default:
r, size = utf8.RuneError, 1
break
}
if nDst+utf8.RuneLen(r) > len(dst) {
err = transform.ErrShortDst
break
}
nDst += utf8.EncodeRune(dst[nDst:], r)
}
return nDst, nSrc, err
}
type eucKREncoder struct{ transform.NopResetter }
func (eucKREncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
r, size := rune(0), 0
for ; nSrc < len(src); nSrc += size {
r = rune(src[nSrc])
// Decode a 1-byte rune.
if r < utf8.RuneSelf {
size = 1
if nDst >= len(dst) {
err = transform.ErrShortDst
break
}
dst[nDst] = uint8(r)
nDst++
continue
} else {
// Decode a multi-byte rune.
r, size = utf8.DecodeRune(src[nSrc:])
if size == 1 {
// All valid runes of size 1 (those below utf8.RuneSelf) were
// handled above. We have invalid UTF-8 or we haven't seen the
// full character yet.
if !atEOF && !utf8.FullRune(src[nSrc:]) {
err = transform.ErrShortSrc
break
}
}
// func init checks that the switch covers all tables.
switch {
case encode0Low <= r && r < encode0High:
if r = rune(encode0[r-encode0Low]); r != 0 {
goto write2
}
case encode1Low <= r && r < encode1High:
if r = rune(encode1[r-encode1Low]); r != 0 {
goto write2
}
case encode2Low <= r && r < encode2High:
if r = rune(encode2[r-encode2Low]); r != 0 {
goto write2
}
case encode3Low <= r && r < encode3High:
if r = rune(encode3[r-encode3Low]); r != 0 {
goto write2
}
case encode4Low <= r && r < encode4High:
if r = rune(encode4[r-encode4Low]); r != 0 {
goto write2
}
case encode5Low <= r && r < encode5High:
if r = rune(encode5[r-encode5Low]); r != 0 {
goto write2
}
case encode6Low <= r && r < encode6High:
if r = rune(encode6[r-encode6Low]); r != 0 {
goto write2
}
}
err = internal.ErrASCIIReplacement
break
}
write2:
if nDst+2 > len(dst) {
err = transform.ErrShortDst
break
}
dst[nDst+0] = uint8(r >> 8)
dst[nDst+1] = uint8(r)
nDst += 2
continue
}
return nDst, nSrc, err
}
func init() {
// Check that the hard-coded encode switch covers all tables.
if numEncodeTables != 7 {
panic("bad numEncodeTables")
}
}
+34152
View File
File diff suppressed because it is too large Load Diff
+12
View File
@@ -0,0 +1,12 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package simplifiedchinese
import (
"golang.org/x/text/encoding"
)
// All is a list of all defined encodings in this package.
var All = []encoding.Encoding{GB18030, GBK, HZGB2312}
+269
View File
@@ -0,0 +1,269 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package simplifiedchinese
import (
"unicode/utf8"
"golang.org/x/text/encoding"
"golang.org/x/text/encoding/internal"
"golang.org/x/text/encoding/internal/identifier"
"golang.org/x/text/transform"
)
var (
// GB18030 is the GB18030 encoding.
GB18030 encoding.Encoding = &gbk18030
// GBK is the GBK encoding. It encodes an extension of the GB2312 character set
// and is also known as Code Page 936.
GBK encoding.Encoding = &gbk
)
var gbk = internal.Encoding{
&internal.SimpleEncoding{
gbkDecoder{gb18030: false},
gbkEncoder{gb18030: false},
},
"GBK",
identifier.GBK,
}
var gbk18030 = internal.Encoding{
&internal.SimpleEncoding{
gbkDecoder{gb18030: true},
gbkEncoder{gb18030: true},
},
"GB18030",
identifier.GB18030,
}
type gbkDecoder struct {
transform.NopResetter
gb18030 bool
}
func (d gbkDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
r, size := rune(0), 0
loop:
for ; nSrc < len(src); nSrc += size {
switch c0 := src[nSrc]; {
case c0 < utf8.RuneSelf:
r, size = rune(c0), 1
// Microsoft's Code Page 936 extends GBK 1.0 to encode the euro sign U+20AC
// as 0x80. The HTML5 specification at http://encoding.spec.whatwg.org/#gbk
// says to treat "gbk" as Code Page 936.
case c0 == 0x80:
r, size = '€', 1
case c0 < 0xff:
if nSrc+1 >= len(src) {
if !atEOF {
err = transform.ErrShortSrc
break loop
}
r, size = utf8.RuneError, 1
goto write
}
c1 := src[nSrc+1]
switch {
case 0x40 <= c1 && c1 < 0x7f:
c1 -= 0x40
case 0x80 <= c1 && c1 < 0xff:
c1 -= 0x41
case d.gb18030 && 0x30 <= c1 && c1 < 0x40:
if nSrc+3 >= len(src) {
if !atEOF {
err = transform.ErrShortSrc
break loop
}
// The second byte here is always ASCII, so we can set size
// to 1 in all cases.
r, size = utf8.RuneError, 1
goto write
}
c2 := src[nSrc+2]
if c2 < 0x81 || 0xff <= c2 {
r, size = utf8.RuneError, 1
goto write
}
c3 := src[nSrc+3]
if c3 < 0x30 || 0x3a <= c3 {
r, size = utf8.RuneError, 1
goto write
}
size = 4
r = ((rune(c0-0x81)*10+rune(c1-0x30))*126+rune(c2-0x81))*10 + rune(c3-0x30)
if r < 39420 {
i, j := 0, len(gb18030)
for i < j {
h := i + (j-i)/2
if r >= rune(gb18030[h][0]) {
i = h + 1
} else {
j = h
}
}
dec := &gb18030[i-1]
r += rune(dec[1]) - rune(dec[0])
goto write
}
r -= 189000
if 0 <= r && r < 0x100000 {
r += 0x10000
} else {
r, size = utf8.RuneError, 1
}
goto write
default:
r, size = utf8.RuneError, 1
goto write
}
r, size = '\ufffd', 2
if i := int(c0-0x81)*190 + int(c1); i < len(decode) {
r = rune(decode[i])
if r == 0 {
r = '\ufffd'
}
}
default:
r, size = utf8.RuneError, 1
}
write:
if nDst+utf8.RuneLen(r) > len(dst) {
err = transform.ErrShortDst
break loop
}
nDst += utf8.EncodeRune(dst[nDst:], r)
}
return nDst, nSrc, err
}
type gbkEncoder struct {
transform.NopResetter
gb18030 bool
}
func (e gbkEncoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
r, r2, size := rune(0), rune(0), 0
for ; nSrc < len(src); nSrc += size {
r = rune(src[nSrc])
// Decode a 1-byte rune.
if r < utf8.RuneSelf {
size = 1
} else {
// Decode a multi-byte rune.
r, size = utf8.DecodeRune(src[nSrc:])
if size == 1 {
// All valid runes of size 1 (those below utf8.RuneSelf) were
// handled above. We have invalid UTF-8 or we haven't seen the
// full character yet.
if !atEOF && !utf8.FullRune(src[nSrc:]) {
err = transform.ErrShortSrc
break
}
}
// func init checks that the switch covers all tables.
switch {
case encode0Low <= r && r < encode0High:
if r2 = rune(encode0[r-encode0Low]); r2 != 0 {
goto write2
}
case encode1Low <= r && r < encode1High:
// Microsoft's Code Page 936 extends GBK 1.0 to encode the euro sign U+20AC
// as 0x80. The HTML5 specification at http://encoding.spec.whatwg.org/#gbk
// says to treat "gbk" as Code Page 936.
if r == '€' {
r = 0x80
goto write1
}
if r2 = rune(encode1[r-encode1Low]); r2 != 0 {
goto write2
}
case encode2Low <= r && r < encode2High:
if r2 = rune(encode2[r-encode2Low]); r2 != 0 {
goto write2
}
case encode3Low <= r && r < encode3High:
if r2 = rune(encode3[r-encode3Low]); r2 != 0 {
goto write2
}
case encode4Low <= r && r < encode4High:
if r2 = rune(encode4[r-encode4Low]); r2 != 0 {
goto write2
}
}
if e.gb18030 {
if r < 0x10000 {
i, j := 0, len(gb18030)
for i < j {
h := i + (j-i)/2
if r >= rune(gb18030[h][1]) {
i = h + 1
} else {
j = h
}
}
dec := &gb18030[i-1]
r += rune(dec[0]) - rune(dec[1])
goto write4
} else if r < 0x110000 {
r += 189000 - 0x10000
goto write4
}
}
err = internal.ErrASCIIReplacement
break
}
write1:
if nDst >= len(dst) {
err = transform.ErrShortDst
break
}
dst[nDst] = uint8(r)
nDst++
continue
write2:
if nDst+2 > len(dst) {
err = transform.ErrShortDst
break
}
dst[nDst+0] = uint8(r2 >> 8)
dst[nDst+1] = uint8(r2)
nDst += 2
continue
write4:
if nDst+4 > len(dst) {
err = transform.ErrShortDst
break
}
dst[nDst+3] = uint8(r%10 + 0x30)
r /= 10
dst[nDst+2] = uint8(r%126 + 0x81)
r /= 126
dst[nDst+1] = uint8(r%10 + 0x30)
r /= 10
dst[nDst+0] = uint8(r + 0x81)
nDst += 4
continue
}
return nDst, nSrc, err
}
func init() {
// Check that the hard-coded encode switch covers all tables.
if numEncodeTables != 5 {
panic("bad numEncodeTables")
}
}
+245
View File
@@ -0,0 +1,245 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package simplifiedchinese
import (
"unicode/utf8"
"golang.org/x/text/encoding"
"golang.org/x/text/encoding/internal"
"golang.org/x/text/encoding/internal/identifier"
"golang.org/x/text/transform"
)
// HZGB2312 is the HZ-GB2312 encoding.
var HZGB2312 encoding.Encoding = &hzGB2312
var hzGB2312 = internal.Encoding{
internal.FuncEncoding{hzGB2312NewDecoder, hzGB2312NewEncoder},
"HZ-GB2312",
identifier.HZGB2312,
}
func hzGB2312NewDecoder() transform.Transformer {
return new(hzGB2312Decoder)
}
func hzGB2312NewEncoder() transform.Transformer {
return new(hzGB2312Encoder)
}
const (
asciiState = iota
gbState
)
type hzGB2312Decoder int
func (d *hzGB2312Decoder) Reset() {
*d = asciiState
}
func (d *hzGB2312Decoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
r, size := rune(0), 0
loop:
for ; nSrc < len(src); nSrc += size {
c0 := src[nSrc]
if c0 >= utf8.RuneSelf {
r, size = utf8.RuneError, 1
goto write
}
if c0 == '~' {
if nSrc+1 >= len(src) {
if !atEOF {
err = transform.ErrShortSrc
break loop
}
r, size = utf8.RuneError, 1
goto write
}
size = 2
switch src[nSrc+1] {
case '{':
*d = gbState
continue
case '}':
*d = asciiState
continue
case '~':
if nDst >= len(dst) {
err = transform.ErrShortDst
break loop
}
dst[nDst] = '~'
nDst++
continue
case '\n':
continue
default:
r = utf8.RuneError
goto write
}
}
if *d == asciiState {
r, size = rune(c0), 1
} else {
if nSrc+1 >= len(src) {
if !atEOF {
err = transform.ErrShortSrc
break loop
}
r, size = utf8.RuneError, 1
goto write
}
size = 2
c1 := src[nSrc+1]
if c0 < 0x21 || 0x7e <= c0 || c1 < 0x21 || 0x7f <= c1 {
// error
} else if i := int(c0-0x01)*190 + int(c1+0x3f); i < len(decode) {
r = rune(decode[i])
if r != 0 {
goto write
}
}
if c1 > utf8.RuneSelf {
// Be consistent and always treat non-ASCII as a single error.
size = 1
}
r = utf8.RuneError
}
write:
if nDst+utf8.RuneLen(r) > len(dst) {
err = transform.ErrShortDst
break loop
}
nDst += utf8.EncodeRune(dst[nDst:], r)
}
return nDst, nSrc, err
}
type hzGB2312Encoder int
func (d *hzGB2312Encoder) Reset() {
*d = asciiState
}
func (e *hzGB2312Encoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
r, size := rune(0), 0
for ; nSrc < len(src); nSrc += size {
r = rune(src[nSrc])
// Decode a 1-byte rune.
if r < utf8.RuneSelf {
size = 1
if r == '~' {
if nDst+2 > len(dst) {
err = transform.ErrShortDst
break
}
dst[nDst+0] = '~'
dst[nDst+1] = '~'
nDst += 2
continue
} else if *e != asciiState {
if nDst+3 > len(dst) {
err = transform.ErrShortDst
break
}
*e = asciiState
dst[nDst+0] = '~'
dst[nDst+1] = '}'
nDst += 2
} else if nDst >= len(dst) {
err = transform.ErrShortDst
break
}
dst[nDst] = uint8(r)
nDst += 1
continue
}
// Decode a multi-byte rune.
r, size = utf8.DecodeRune(src[nSrc:])
if size == 1 {
// All valid runes of size 1 (those below utf8.RuneSelf) were
// handled above. We have invalid UTF-8 or we haven't seen the
// full character yet.
if !atEOF && !utf8.FullRune(src[nSrc:]) {
err = transform.ErrShortSrc
break
}
}
// func init checks that the switch covers all tables.
switch {
case encode0Low <= r && r < encode0High:
if r = rune(encode0[r-encode0Low]); r != 0 {
goto writeGB
}
case encode1Low <= r && r < encode1High:
if r = rune(encode1[r-encode1Low]); r != 0 {
goto writeGB
}
case encode2Low <= r && r < encode2High:
if r = rune(encode2[r-encode2Low]); r != 0 {
goto writeGB
}
case encode3Low <= r && r < encode3High:
if r = rune(encode3[r-encode3Low]); r != 0 {
goto writeGB
}
case encode4Low <= r && r < encode4High:
if r = rune(encode4[r-encode4Low]); r != 0 {
goto writeGB
}
}
terminateInASCIIState:
// Switch back to ASCII state in case of error so that an ASCII
// replacement character can be written in the correct state.
if *e != asciiState {
if nDst+2 > len(dst) {
err = transform.ErrShortDst
break
}
dst[nDst+0] = '~'
dst[nDst+1] = '}'
nDst += 2
}
err = internal.ErrASCIIReplacement
break
writeGB:
c0 := uint8(r>>8) - 0x80
c1 := uint8(r) - 0x80
if c0 < 0x21 || 0x7e <= c0 || c1 < 0x21 || 0x7f <= c1 {
goto terminateInASCIIState
}
if *e == asciiState {
if nDst+4 > len(dst) {
err = transform.ErrShortDst
break
}
*e = gbState
dst[nDst+0] = '~'
dst[nDst+1] = '{'
nDst += 2
} else if nDst+2 > len(dst) {
err = transform.ErrShortDst
break
}
dst[nDst+0] = c0
dst[nDst+1] = c1
nDst += 2
continue
}
// TODO: should one always terminate in ASCII state to make it safe to
// concatenate two HZ-GB2312-encoded strings?
return nDst, nSrc, err
}
File diff suppressed because it is too large Load Diff
+199
View File
@@ -0,0 +1,199 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package traditionalchinese
import (
"unicode/utf8"
"golang.org/x/text/encoding"
"golang.org/x/text/encoding/internal"
"golang.org/x/text/encoding/internal/identifier"
"golang.org/x/text/transform"
)
// All is a list of all defined encodings in this package.
var All = []encoding.Encoding{Big5}
// Big5 is the Big5 encoding, also known as Code Page 950.
var Big5 encoding.Encoding = &big5
var big5 = internal.Encoding{
&internal.SimpleEncoding{big5Decoder{}, big5Encoder{}},
"Big5",
identifier.Big5,
}
type big5Decoder struct{ transform.NopResetter }
func (big5Decoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
r, size, s := rune(0), 0, ""
loop:
for ; nSrc < len(src); nSrc += size {
switch c0 := src[nSrc]; {
case c0 < utf8.RuneSelf:
r, size = rune(c0), 1
case 0x81 <= c0 && c0 < 0xff:
if nSrc+1 >= len(src) {
if !atEOF {
err = transform.ErrShortSrc
break loop
}
r, size = utf8.RuneError, 1
goto write
}
c1 := src[nSrc+1]
switch {
case 0x40 <= c1 && c1 < 0x7f:
c1 -= 0x40
case 0xa1 <= c1 && c1 < 0xff:
c1 -= 0x62
case c1 < 0x40:
r, size = utf8.RuneError, 1
goto write
default:
r, size = utf8.RuneError, 2
goto write
}
r, size = '\ufffd', 2
if i := int(c0-0x81)*157 + int(c1); i < len(decode) {
if 1133 <= i && i < 1167 {
// The two-rune special cases for LATIN CAPITAL / SMALL E WITH CIRCUMFLEX
// AND MACRON / CARON are from http://encoding.spec.whatwg.org/#big5
switch i {
case 1133:
s = "\u00CA\u0304"
goto writeStr
case 1135:
s = "\u00CA\u030C"
goto writeStr
case 1164:
s = "\u00EA\u0304"
goto writeStr
case 1166:
s = "\u00EA\u030C"
goto writeStr
}
}
r = rune(decode[i])
if r == 0 {
r = '\ufffd'
}
}
default:
r, size = utf8.RuneError, 1
}
write:
if nDst+utf8.RuneLen(r) > len(dst) {
err = transform.ErrShortDst
break loop
}
nDst += utf8.EncodeRune(dst[nDst:], r)
continue loop
writeStr:
if nDst+len(s) > len(dst) {
err = transform.ErrShortDst
break loop
}
nDst += copy(dst[nDst:], s)
continue loop
}
return nDst, nSrc, err
}
type big5Encoder struct{ transform.NopResetter }
func (big5Encoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) {
r, size := rune(0), 0
for ; nSrc < len(src); nSrc += size {
r = rune(src[nSrc])
// Decode a 1-byte rune.
if r < utf8.RuneSelf {
size = 1
if nDst >= len(dst) {
err = transform.ErrShortDst
break
}
dst[nDst] = uint8(r)
nDst++
continue
} else {
// Decode a multi-byte rune.
r, size = utf8.DecodeRune(src[nSrc:])
if size == 1 {
// All valid runes of size 1 (those below utf8.RuneSelf) were
// handled above. We have invalid UTF-8 or we haven't seen the
// full character yet.
if !atEOF && !utf8.FullRune(src[nSrc:]) {
err = transform.ErrShortSrc
break
}
}
}
if r >= utf8.RuneSelf {
// func init checks that the switch covers all tables.
switch {
case encode0Low <= r && r < encode0High:
if r = rune(encode0[r-encode0Low]); r != 0 {
goto write2
}
case encode1Low <= r && r < encode1High:
if r = rune(encode1[r-encode1Low]); r != 0 {
goto write2
}
case encode2Low <= r && r < encode2High:
if r = rune(encode2[r-encode2Low]); r != 0 {
goto write2
}
case encode3Low <= r && r < encode3High:
if r = rune(encode3[r-encode3Low]); r != 0 {
goto write2
}
case encode4Low <= r && r < encode4High:
if r = rune(encode4[r-encode4Low]); r != 0 {
goto write2
}
case encode5Low <= r && r < encode5High:
if r = rune(encode5[r-encode5Low]); r != 0 {
goto write2
}
case encode6Low <= r && r < encode6High:
if r = rune(encode6[r-encode6Low]); r != 0 {
goto write2
}
case encode7Low <= r && r < encode7High:
if r = rune(encode7[r-encode7Low]); r != 0 {
goto write2
}
}
err = internal.ErrASCIIReplacement
break
}
write2:
if nDst+2 > len(dst) {
err = transform.ErrShortDst
break
}
dst[nDst+0] = uint8(r >> 8)
dst[nDst+1] = uint8(r)
nDst += 2
continue
}
return nDst, nSrc, err
}
func init() {
// Check that the hard-coded encode switch covers all tables.
if numEncodeTables != 8 {
panic("bad numEncodeTables")
}
}
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More