github.com/xiyichan/dm8@v0.0.0-20211213021639-be727be3e136/n.go (about) 1 /* 2 * Copyright (c) 2000-2018, 达梦数据库有限公司. 3 * All rights reserved. 4 */ 5 package dm 6 7 import ( 8 "io" 9 ) 10 11 type DmClob struct { 12 lob 13 data []rune 14 serverEncoding string 15 } 16 17 func newDmClob() *DmClob { 18 return &DmClob{ 19 lob: lob{ 20 inRow: true, 21 groupId: -1, 22 fileId: -1, 23 pageNo: -1, 24 readOver: false, 25 local: true, 26 updateable: true, 27 length: -1, 28 compatibleOracle: false, 29 fetchAll: false, 30 freed: false, 31 modify: false, 32 }, 33 } 34 } 35 36 func newClobFromDB(value []byte, conn *DmConnection, column *column, fetchAll bool) *DmClob { 37 var clob = newDmClob() 38 clob.connection = conn 39 clob.lobFlag = LOB_FLAG_CHAR 40 clob.compatibleOracle = conn.CompatibleOracle() 41 clob.local = false 42 clob.updateable = !column.readonly 43 clob.tabId = column.lobTabId 44 clob.colId = column.lobColId 45 46 clob.inRow = Dm_build_599.Dm_build_692(value, NBLOB_HEAD_IN_ROW_FLAG) == LOB_IN_ROW 47 clob.blobId = Dm_build_599.Dm_build_706(value, NBLOB_HEAD_BLOBID) 48 if !clob.inRow { 49 clob.groupId = Dm_build_599.Dm_build_696(value, NBLOB_HEAD_OUTROW_GROUPID) 50 clob.fileId = Dm_build_599.Dm_build_696(value, NBLOB_HEAD_OUTROW_FILEID) 51 clob.pageNo = Dm_build_599.Dm_build_701(value, NBLOB_HEAD_OUTROW_PAGENO) 52 } 53 if conn.NewLobFlag { 54 clob.tabId = Dm_build_599.Dm_build_701(value, NBLOB_EX_HEAD_TABLE_ID) 55 clob.colId = Dm_build_599.Dm_build_696(value, NBLOB_EX_HEAD_COL_ID) 56 clob.rowId = Dm_build_599.Dm_build_706(value, NBLOB_EX_HEAD_ROW_ID) 57 clob.exGroupId = Dm_build_599.Dm_build_696(value, NBLOB_EX_HEAD_FPA_GRPID) 58 clob.exFileId = Dm_build_599.Dm_build_696(value, NBLOB_EX_HEAD_FPA_FILEID) 59 clob.exPageNo = Dm_build_599.Dm_build_701(value, NBLOB_EX_HEAD_FPA_PAGENO) 60 } 61 clob.resetCurrentInfo() 62 63 clob.serverEncoding = conn.getServerEncoding() 64 if clob.inRow { 65 if conn.NewLobFlag { 66 clob.data = []rune(Dm_build_599.Dm_build_753(value, NBLOB_EX_HEAD_SIZE, int(clob.getLengthFromHead(value)), clob.serverEncoding, conn)) 67 } else { 68 clob.data = []rune(Dm_build_599.Dm_build_753(value, NBLOB_INROW_HEAD_SIZE, int(clob.getLengthFromHead(value)), clob.serverEncoding, conn)) 69 } 70 clob.length = int64(len(clob.data)) 71 } else if fetchAll { 72 clob.loadAllData() 73 } 74 return clob 75 } 76 77 func newClobOfLocal(value string, conn *DmConnection) *DmClob { 78 var clob = newDmClob() 79 clob.connection = conn 80 clob.lobFlag = LOB_FLAG_CHAR 81 clob.data = []rune(value) 82 clob.length = int64(len(clob.data)) 83 return clob 84 } 85 86 func NewClob(value string) *DmClob { 87 var clob = newDmClob() 88 89 clob.lobFlag = LOB_FLAG_CHAR 90 clob.data = []rune(value) 91 clob.length = int64(len(clob.data)) 92 return clob 93 } 94 95 func (clob *DmClob) ReadString(pos int, length int) (result string, err error) { 96 result, err = clob.getSubString(int64(pos), int32(length)) 97 if err != nil { 98 return 99 } 100 if len(result) == 0 { 101 err = io.EOF 102 return 103 } 104 return 105 } 106 107 func (clob *DmClob) WriteString(pos int, s string) (n int, err error) { 108 if err = clob.checkFreed(); err != nil { 109 return 110 } 111 if pos < 1 { 112 err = ECGO_INVALID_LENGTH_OR_OFFSET.throw() 113 return 114 } 115 if !clob.updateable { 116 err = ECGO_RESULTSET_IS_READ_ONLY.throw() 117 return 118 } 119 pos -= 1 120 if clob.local || clob.fetchAll { 121 if int64(pos) > clob.length { 122 err = ECGO_INVALID_LENGTH_OR_OFFSET.throw() 123 return 124 } 125 clob.setLocalData(pos, s) 126 n = len(s) 127 } else { 128 if err = clob.connection.checkClosed(); err != nil { 129 return -1, err 130 } 131 var writeLen, err = clob.connection.Access.dm_build_1478(clob, pos, s, clob.serverEncoding) 132 if err != nil { 133 return -1, err 134 } 135 136 if clob.groupId == -1 { 137 clob.setLocalData(pos, s) 138 } else { 139 clob.inRow = false 140 clob.length = -1 141 } 142 n = writeLen 143 } 144 clob.modify = true 145 return 146 } 147 148 func (clob *DmClob) Truncate(length int64) error { 149 var err error 150 if err = clob.checkFreed(); err != nil { 151 return err 152 } 153 if length < 0 { 154 return ECGO_INVALID_LENGTH_OR_OFFSET.throw() 155 } 156 if !clob.updateable { 157 return ECGO_RESULTSET_IS_READ_ONLY.throw() 158 } 159 if clob.local || clob.fetchAll { 160 if length >= int64(len(clob.data)) { 161 return nil 162 } 163 clob.data = clob.data[0:length] 164 clob.length = int64(len(clob.data)) 165 } else { 166 if err = clob.connection.checkClosed(); err != nil { 167 return err 168 } 169 clob.length, err = clob.connection.Access.dm_build_1508(&clob.lob, int(length)) 170 if err != nil { 171 return err 172 } 173 if clob.groupId == -1 { 174 clob.data = clob.data[0:clob.length] 175 } 176 } 177 clob.modify = true 178 return nil 179 } 180 181 func (dest *DmClob) Scan(src interface{}) error { 182 if dest == nil { 183 return ECGO_STORE_IN_NIL_POINTER.throw() 184 } 185 switch src := src.(type) { 186 case nil: 187 *dest = *new(DmClob) 188 return nil 189 case string: 190 *dest = *NewClob(src) 191 return nil 192 case *DmClob: 193 *dest = *src 194 return nil 195 default: 196 return UNSUPPORTED_SCAN 197 } 198 } 199 200 func (clob *DmClob) getSubString(pos int64, len int32) (string, error) { 201 var err error 202 var leaveLength int64 203 if err = clob.checkFreed(); err != nil { 204 return "", err 205 } 206 if pos < 1 || len < 0 { 207 return "", ECGO_INVALID_LENGTH_OR_OFFSET.throw() 208 } 209 pos = pos - 1 210 if leaveLength, err = clob.GetLength(); err != nil { 211 return "", err 212 } 213 if pos > leaveLength { 214 pos = leaveLength 215 } 216 leaveLength -= pos 217 if leaveLength < 0 { 218 return "", ECGO_INVALID_LENGTH_OR_OFFSET.throw() 219 } 220 if int64(len) > leaveLength { 221 len = int32(leaveLength) 222 } 223 if clob.local || clob.inRow || clob.fetchAll { 224 if pos > clob.length { 225 return "", ECGO_INVALID_LENGTH_OR_OFFSET.throw() 226 } 227 return string(clob.data[pos : pos+int64(len)]), nil 228 } else { 229 230 return clob.connection.Access.dm_build_1467(clob, int32(pos), len) 231 } 232 } 233 234 func (clob *DmClob) loadAllData() { 235 clob.checkFreed() 236 if clob.local || clob.inRow || clob.fetchAll { 237 return 238 } 239 len, _ := clob.GetLength() 240 s, _ := clob.getSubString(1, int32(len)) 241 clob.data = []rune(s) 242 clob.fetchAll = true 243 } 244 245 func (clob *DmClob) setLocalData(pos int, str string) { 246 if pos+len(str) >= int(clob.length) { 247 clob.data = []rune(string(clob.data[0:pos]) + str) 248 } else { 249 clob.data = []rune(string(clob.data[0:pos]) + str + string(clob.data[pos+len(str):len(clob.data)])) 250 } 251 clob.length = int64(len(clob.data)) 252 }