gitee.com/curryzheng/dm@v0.0.1/l.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 DmBlob struct { 13 lob 14 data []byte 15 offset int64 16 } 17 18 func newDmBlob() *DmBlob { 19 return &DmBlob{ 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 offset: 1, 36 } 37 } 38 39 func newBlobFromDB(value []byte, conn *DmConnection, column *column, fetchAll bool) *DmBlob { 40 var blob = newDmBlob() 41 blob.connection = conn 42 blob.lobFlag = LOB_FLAG_BYTE 43 blob.compatibleOracle = conn.CompatibleOracle() 44 blob.local = false 45 blob.updateable = !column.readonly 46 blob.tabId = column.lobTabId 47 blob.colId = column.lobColId 48 49 blob.inRow = Dm_build_1.Dm_build_94(value, NBLOB_HEAD_IN_ROW_FLAG) == LOB_IN_ROW 50 blob.blobId = Dm_build_1.Dm_build_108(value, NBLOB_HEAD_BLOBID) 51 if !blob.inRow { 52 blob.groupId = Dm_build_1.Dm_build_98(value, NBLOB_HEAD_OUTROW_GROUPID) 53 blob.fileId = Dm_build_1.Dm_build_98(value, NBLOB_HEAD_OUTROW_FILEID) 54 blob.pageNo = Dm_build_1.Dm_build_103(value, NBLOB_HEAD_OUTROW_PAGENO) 55 } 56 if conn.NewLobFlag { 57 blob.tabId = Dm_build_1.Dm_build_103(value, NBLOB_EX_HEAD_TABLE_ID) 58 blob.colId = Dm_build_1.Dm_build_98(value, NBLOB_EX_HEAD_COL_ID) 59 blob.rowId = Dm_build_1.Dm_build_108(value, NBLOB_EX_HEAD_ROW_ID) 60 blob.exGroupId = Dm_build_1.Dm_build_98(value, NBLOB_EX_HEAD_FPA_GRPID) 61 blob.exFileId = Dm_build_1.Dm_build_98(value, NBLOB_EX_HEAD_FPA_FILEID) 62 blob.exPageNo = Dm_build_1.Dm_build_103(value, NBLOB_EX_HEAD_FPA_PAGENO) 63 } 64 blob.resetCurrentInfo() 65 66 blob.length = blob.getLengthFromHead(value) 67 if blob.inRow { 68 blob.data = make([]byte, blob.length) 69 if conn.NewLobFlag { 70 Dm_build_1.Dm_build_57(blob.data, 0, value, NBLOB_EX_HEAD_SIZE, len(blob.data)) 71 } else { 72 Dm_build_1.Dm_build_57(blob.data, 0, value, NBLOB_INROW_HEAD_SIZE, len(blob.data)) 73 } 74 } else if fetchAll { 75 blob.loadAllData() 76 } 77 return blob 78 } 79 80 func newBlobOfLocal(value []byte, conn *DmConnection) *DmBlob { 81 var blob = newDmBlob() 82 blob.connection = conn 83 blob.lobFlag = LOB_FLAG_BYTE 84 blob.data = value 85 blob.length = int64(len(blob.data)) 86 return blob 87 } 88 89 func NewBlob(value []byte) *DmBlob { 90 var blob = newDmBlob() 91 92 blob.lobFlag = LOB_FLAG_BYTE 93 blob.data = value 94 blob.length = int64(len(blob.data)) 95 return blob 96 } 97 98 func (blob *DmBlob) Read(dest []byte) (n int, err error) { 99 if err = blob.checkValid(); err != nil { 100 return 101 } 102 result, err := blob.getBytes(blob.offset, int32(len(dest))) 103 if err != nil { 104 return 0, err 105 } 106 blob.offset += int64(len(result)) 107 copy(dest, result) 108 if len(result) == 0 { 109 return 0, io.EOF 110 } 111 return len(result), nil 112 } 113 114 func (blob *DmBlob) ReadAt(pos int, dest []byte) (n int, err error) { 115 if err = blob.checkValid(); err != nil { 116 return 117 } 118 result, err := blob.getBytes(int64(pos), int32(len(dest))) 119 if err != nil { 120 return 0, err 121 } 122 if len(result) == 0 { 123 return 0, io.EOF 124 } 125 copy(dest[0:len(result)], result) 126 return len(result), nil 127 } 128 129 func (blob *DmBlob) Write(pos int, src []byte) (n int, err error) { 130 if err = blob.checkValid(); err != nil { 131 return 132 } 133 if err = blob.checkFreed(); err != nil { 134 return 135 } 136 if pos < 1 { 137 err = ECGO_INVALID_LENGTH_OR_OFFSET.throw() 138 return 139 } 140 if !blob.updateable { 141 err = ECGO_RESULTSET_IS_READ_ONLY.throw() 142 return 143 } 144 pos -= 1 145 if blob.local || blob.fetchAll { 146 if int64(pos) > blob.length { 147 err = ECGO_INVALID_LENGTH_OR_OFFSET.throw() 148 return 149 } 150 blob.setLocalData(pos, src) 151 n = len(src) 152 } else { 153 if err = blob.connection.checkClosed(); err != nil { 154 return -1, err 155 } 156 var writeLen, err = blob.connection.Access.dm_build_900(blob, pos, src) 157 if err != nil { 158 return -1, err 159 } 160 161 if blob.groupId == -1 { 162 blob.setLocalData(pos, src) 163 } else { 164 blob.inRow = false 165 blob.length = -1 166 } 167 n = writeLen 168 169 } 170 blob.modify = true 171 return 172 } 173 174 func (blob *DmBlob) Truncate(length int64) error { 175 var err error 176 if err = blob.checkValid(); err != nil { 177 return err 178 } 179 if err = blob.checkFreed(); err != nil { 180 return err 181 } 182 if length < 0 { 183 return ECGO_INVALID_LENGTH_OR_OFFSET.throw() 184 } 185 if !blob.updateable { 186 return ECGO_RESULTSET_IS_READ_ONLY.throw() 187 } 188 if blob.local || blob.fetchAll { 189 if length >= int64(len(blob.data)) { 190 return nil 191 } 192 tmp := make([]byte, length) 193 Dm_build_1.Dm_build_57(tmp, 0, blob.data, 0, len(tmp)) 194 blob.data = tmp 195 blob.length = int64(len(tmp)) 196 } else { 197 if err = blob.connection.checkClosed(); err != nil { 198 return err 199 } 200 blob.length, err = blob.connection.Access.dm_build_914(&blob.lob, int(length)) 201 if err != nil { 202 return err 203 } 204 if blob.groupId == -1 { 205 tmp := make([]byte, blob.length) 206 Dm_build_1.Dm_build_57(tmp, 0, blob.data, 0, int(blob.length)) 207 blob.data = tmp 208 } 209 } 210 blob.modify = true 211 return nil 212 } 213 214 func (dest *DmBlob) Scan(src interface{}) error { 215 if dest == nil { 216 return ECGO_STORE_IN_NIL_POINTER.throw() 217 } 218 switch src := src.(type) { 219 case nil: 220 *dest = *new(DmBlob) 221 222 (*dest).Valid = false 223 return nil 224 case []byte: 225 *dest = *NewBlob(src) 226 return nil 227 case *DmBlob: 228 *dest = *src 229 return nil 230 default: 231 return UNSUPPORTED_SCAN.throw() 232 } 233 } 234 235 func (blob DmBlob) Value() (driver.Value, error) { 236 if !blob.Valid { 237 return nil, nil 238 } 239 return blob, nil 240 } 241 242 func (blob *DmBlob) getBytes(pos int64, length int32) ([]byte, error) { 243 var err error 244 var leaveLength int64 245 if err = blob.checkFreed(); err != nil { 246 return nil, err 247 } 248 if pos < 1 || length < 0 { 249 return nil, ECGO_INVALID_LENGTH_OR_OFFSET.throw() 250 } 251 pos = pos - 1 252 if leaveLength, err = blob.GetLength(); err != nil { 253 return nil, err 254 } 255 leaveLength -= pos 256 if leaveLength < 0 { 257 return nil, ECGO_INVALID_LENGTH_OR_OFFSET.throw() 258 } 259 if int64(length) > leaveLength { 260 length = int32(leaveLength) 261 } 262 if blob.local || blob.inRow || blob.fetchAll { 263 return blob.data[pos : pos+int64(length)], nil 264 } else { 265 266 return blob.connection.Access.dm_build_863(blob, int32(pos), length) 267 } 268 } 269 270 func (blob *DmBlob) loadAllData() { 271 blob.checkFreed() 272 if blob.local || blob.inRow || blob.fetchAll { 273 return 274 } 275 len, _ := blob.GetLength() 276 blob.data, _ = blob.getBytes(1, int32(len)) 277 blob.fetchAll = true 278 } 279 280 func (blob *DmBlob) setLocalData(pos int, p []byte) { 281 if pos+len(p) >= int(blob.length) { 282 var tmp = make([]byte, pos+len(p)) 283 Dm_build_1.Dm_build_57(tmp, 0, blob.data, 0, pos) 284 Dm_build_1.Dm_build_57(tmp, pos, p, 0, len(p)) 285 blob.data = tmp 286 } else { 287 Dm_build_1.Dm_build_57(blob.data, pos, p, 0, len(p)) 288 } 289 blob.length = int64(len(blob.data)) 290 }