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