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  }