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