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