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