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  }