b43f968b6c
- 在应用程序中新增对达梦数据库(DM)的配置和连接支持 - 实现 SetDmDB 函数以配置达梦数据库连接 - 更新数据库操作逻辑,支持达梦特有的 SQL 语法和功能 - 在相关文件中添加达梦数据库的处理逻辑,包括表创建、数据插入和查询 - 更新 go.mod 和 go.sum 文件以引入达梦数据库驱动 - 增强文档,详细说明达梦数据库的配置和使用方法
280 lines
6.5 KiB
Go
280 lines
6.5 KiB
Go
/*
|
|
* 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"
|
|
}
|