github.com/wanlay/gorm-dm8@v1.0.5/dmr/u.go (about)

     1  /*
     2   * Copyright (c) 2000-2018, 达梦数据库有限公司.
     3   * All rights reserved.
     4   */
     5  package dmr
     6  
     7  import (
     8  	"container/list"
     9  	"context"
    10  	"database/sql"
    11  	"database/sql/driver"
    12  	"fmt"
    13  	"io"
    14  	"math/big"
    15  	"reflect"
    16  	"strconv"
    17  	"strings"
    18  	"time"
    19  
    20  	"github.com/wanlay/gorm-dm8/dmr/util"
    21  )
    22  
    23  const (
    24  	BIND_IN byte = 0x01
    25  
    26  	BIND_OUT byte = 0x10
    27  )
    28  
    29  var rp = newRsPool()
    30  
    31  type DmStatement struct {
    32  	filterable
    33  
    34  	dmConn    *DmConnection
    35  	rsMap     map[int16]*innerRows
    36  	inUse     bool
    37  	innerUsed bool
    38  
    39  	innerExec bool
    40  
    41  	id int32
    42  
    43  	cursorName string
    44  
    45  	readBaseColName bool
    46  
    47  	execInfo *execRetInfo
    48  
    49  	resultSetType int
    50  
    51  	resultSetConcurrency int
    52  
    53  	resultSetHoldability int
    54  
    55  	nativeSql string
    56  
    57  	maxFieldSize int
    58  
    59  	maxRows int64
    60  
    61  	escapeProcessing bool
    62  
    63  	queryTimeout int32
    64  
    65  	fetchDirection int
    66  
    67  	fetchSize int
    68  
    69  	cursorUpdateRow int64
    70  
    71  	closeOnCompletion bool
    72  
    73  	isBatch bool
    74  
    75  	closed bool
    76  
    77  	columns []column
    78  
    79  	params []parameter
    80  
    81  	paramCount int32
    82  
    83  	curRowBindIndicator []byte
    84  
    85  	preExec bool
    86  }
    87  
    88  type stmtPoolInfo struct {
    89  	id int32
    90  
    91  	cursorName string
    92  
    93  	readBaseColName bool
    94  }
    95  
    96  type rsPoolKey struct {
    97  	dbGuid        string
    98  	currentSchema string
    99  	sql           string
   100  	paramCount    int
   101  }
   102  
   103  func newRsPoolKey(stmt *DmStatement, sql string) rsPoolKey {
   104  	rpk := new(rsPoolKey)
   105  	rpk.dbGuid = stmt.dmConn.Guid
   106  	rpk.currentSchema = stmt.dmConn.Schema
   107  	rpk.paramCount = int(stmt.paramCount)
   108  
   109  	rpk.sql = sql
   110  	return *rpk
   111  }
   112  
   113  func (key rsPoolKey) equals(destKey rsPoolKey) bool {
   114  	return key.dbGuid == destKey.dbGuid &&
   115  		key.currentSchema == destKey.currentSchema &&
   116  		key.sql == destKey.sql &&
   117  		key.paramCount == destKey.paramCount
   118  
   119  }
   120  
   121  type rsPoolValue struct {
   122  	m_lastChkTime int
   123  	m_TbIds       []int32
   124  	m_TbTss       []int64
   125  	execInfo      *execRetInfo
   126  }
   127  
   128  func newRsPoolValue(execInfo *execRetInfo) rsPoolValue {
   129  	rpv := new(rsPoolValue)
   130  	rpv.execInfo = execInfo
   131  	rpv.m_lastChkTime = time.Now().Nanosecond()
   132  	copy(rpv.m_TbIds, execInfo.tbIds)
   133  	copy(rpv.m_TbTss, execInfo.tbTss)
   134  	return *rpv
   135  }
   136  
   137  func (rpv rsPoolValue) refreshed(conn *DmConnection) (bool, error) {
   138  
   139  	if conn.dmConnector.rsRefreshFreq == 0 {
   140  		return false, nil
   141  	}
   142  
   143  	if rpv.m_lastChkTime+conn.dmConnector.rsRefreshFreq*int(time.Second) > time.Now().Nanosecond() {
   144  		return false, nil
   145  	}
   146  
   147  	tss, err := conn.Access.Dm_build_482(interface{}(rpv.m_TbIds).([]uint32))
   148  	if err != nil {
   149  		return false, err
   150  	}
   151  	rpv.m_lastChkTime = time.Now().Nanosecond()
   152  
   153  	var tbCount int
   154  	if tss != nil {
   155  		tbCount = len(tss)
   156  	}
   157  
   158  	if tbCount != len(rpv.m_TbTss) {
   159  		return true, nil
   160  	}
   161  
   162  	for i := 0; i < tbCount; i++ {
   163  		if rpv.m_TbTss[i] != tss[i] {
   164  			return true, nil
   165  		}
   166  
   167  	}
   168  	return false, nil
   169  }
   170  
   171  func (rpv rsPoolValue) getResultSet(stmt *DmStatement) *innerRows {
   172  	destDatas := rpv.execInfo.rsDatas
   173  	var totalRows int
   174  	if rpv.execInfo.rsDatas != nil {
   175  		totalRows = len(rpv.execInfo.rsDatas)
   176  	}
   177  
   178  	if stmt.maxRows > 0 && stmt.maxRows < int64(totalRows) {
   179  		destDatas = make([][][]byte, stmt.maxRows)
   180  		copy(destDatas[:len(destDatas)], rpv.execInfo.rsDatas[:len(destDatas)])
   181  	}
   182  
   183  	rs := newLocalInnerRows(stmt, stmt.columns, destDatas)
   184  	rs.id = 1
   185  	return rs
   186  }
   187  
   188  func (rpv rsPoolValue) getDataLen() int {
   189  	return rpv.execInfo.rsSizeof
   190  }
   191  
   192  type rsPool struct {
   193  	rsMap        map[rsPoolKey]rsPoolValue
   194  	rsList       *list.List
   195  	totalDataLen int
   196  }
   197  
   198  func newRsPool() *rsPool {
   199  	rp := new(rsPool)
   200  	rp.rsMap = make(map[rsPoolKey]rsPoolValue, 100)
   201  	rp.rsList = list.New()
   202  	return rp
   203  }
   204  
   205  func (rp *rsPool) removeInList(key rsPoolKey) {
   206  	for e := rp.rsList.Front(); e != nil && e.Value.(rsPoolKey).equals(key); e = e.Next() {
   207  		rp.rsList.Remove(e)
   208  	}
   209  }
   210  
   211  func (rp *rsPool) put(stmt *DmStatement, sql string, execInfo *execRetInfo) {
   212  	var dataLen int
   213  	if execInfo != nil {
   214  		dataLen = execInfo.rsSizeof
   215  	}
   216  
   217  	cacheSize := stmt.dmConn.dmConnector.rsCacheSize * 1024 * 1024
   218  
   219  	for rp.totalDataLen+dataLen > cacheSize {
   220  		if rp.totalDataLen == 0 {
   221  			return
   222  		}
   223  
   224  		lk := rp.rsList.Back().Value.(rsPoolKey)
   225  		rp.totalDataLen -= rp.rsMap[lk].getDataLen()
   226  		rp.rsList.Remove(rp.rsList.Back())
   227  		delete(rp.rsMap, rp.rsList.Back().Value.(rsPoolKey))
   228  	}
   229  
   230  	key := newRsPoolKey(stmt, sql)
   231  	value := newRsPoolValue(execInfo)
   232  
   233  	if _, ok := rp.rsMap[key]; !ok {
   234  		rp.rsList.PushFront(key)
   235  	} else {
   236  		rp.removeInList(key)
   237  		rp.rsList.PushFront(key)
   238  	}
   239  
   240  	rp.rsMap[key] = value
   241  	rp.totalDataLen += dataLen
   242  }
   243  
   244  func (rp *rsPool) get(stmt *DmStatement, sql string) (*rsPoolValue, error) {
   245  	key := newRsPoolKey(stmt, sql)
   246  
   247  	v, ok := rp.rsMap[key]
   248  	if ok {
   249  		b, err := v.refreshed(stmt.dmConn)
   250  		if err != nil {
   251  			return nil, err
   252  		}
   253  
   254  		if b {
   255  			rp.removeInList(key)
   256  			delete(rp.rsMap, key)
   257  			return nil, nil
   258  		}
   259  
   260  		rp.removeInList(key)
   261  		rp.rsList.PushFront(key)
   262  		return &v, nil
   263  	} else {
   264  		return nil, nil
   265  	}
   266  }
   267  
   268  func (s *DmStatement) Close() error {
   269  	if s.closed {
   270  		return nil
   271  	}
   272  	if len(s.filterChain.filters) == 0 {
   273  		return s.close()
   274  	}
   275  	return s.filterChain.reset().DmStatementClose(s)
   276  }
   277  
   278  func (s *DmStatement) NumInput() int {
   279  	if err := s.checkClosed(); err != nil {
   280  		return 0
   281  	}
   282  	if len(s.filterChain.filters) == 0 {
   283  		return s.numInput()
   284  	}
   285  	return s.filterChain.reset().DmStatementNumInput(s)
   286  }
   287  
   288  func (s *DmStatement) Exec(args []driver.Value) (driver.Result, error) {
   289  	if err := s.checkClosed(); err != nil {
   290  		return nil, err
   291  	}
   292  	if len(s.filterChain.filters) == 0 {
   293  		return s.exec(args)
   294  	}
   295  	return s.filterChain.reset().DmStatementExec(s, args)
   296  }
   297  
   298  func (s *DmStatement) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
   299  	if err := s.checkClosed(); err != nil {
   300  		return nil, err
   301  	}
   302  	if len(s.filterChain.filters) == 0 {
   303  		return s.execContext(ctx, args)
   304  	}
   305  	return s.filterChain.reset().DmStatementExecContext(s, ctx, args)
   306  }
   307  
   308  func (s *DmStatement) Query(args []driver.Value) (driver.Rows, error) {
   309  	if err := s.checkClosed(); err != nil {
   310  		return nil, err
   311  	}
   312  	if len(s.filterChain.filters) == 0 {
   313  		return s.query(args)
   314  	}
   315  	return s.filterChain.reset().DmStatementQuery(s, args)
   316  }
   317  
   318  func (s *DmStatement) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
   319  	if err := s.checkClosed(); err != nil {
   320  		return nil, err
   321  	}
   322  	if len(s.filterChain.filters) == 0 {
   323  		return s.queryContext(ctx, args)
   324  	}
   325  	return s.filterChain.reset().DmStatementQueryContext(s, ctx, args)
   326  }
   327  
   328  func (s *DmStatement) CheckNamedValue(nv *driver.NamedValue) error {
   329  	if len(s.filterChain.filters) == 0 {
   330  		return s.checkNamedValue(nv)
   331  	}
   332  	return s.filterChain.reset().DmStatementCheckNamedValue(s, nv)
   333  }
   334  
   335  func (st *DmStatement) prepare() error {
   336  	var err error
   337  	if st.dmConn.dmConnector.escapeProcess {
   338  		st.nativeSql, err = st.dmConn.escape(st.nativeSql, st.dmConn.dmConnector.keyWords)
   339  		if err != nil {
   340  			return err
   341  		}
   342  	}
   343  
   344  	st.execInfo, err = st.dmConn.Access.Dm_build_407(st, Dm_build_685)
   345  	if err != nil {
   346  		return err
   347  	}
   348  	st.curRowBindIndicator = make([]byte, st.paramCount)
   349  	return nil
   350  }
   351  
   352  func (stmt *DmStatement) close() error {
   353  	stmt.inUse = true
   354  	if stmt.dmConn.stmtPool != nil && len(stmt.dmConn.stmtPool) < stmt.dmConn.dmConnector.stmtPoolMaxSize {
   355  		stmt.pool()
   356  		return nil
   357  	} else {
   358  		return stmt.free()
   359  	}
   360  }
   361  
   362  func (stmt *DmStatement) numInput() int {
   363  	return int(stmt.paramCount)
   364  }
   365  
   366  func (stmt *DmStatement) checkNamedValue(nv *driver.NamedValue) error {
   367  	var err error
   368  	var cvt = converter{stmt.dmConn, false}
   369  	nv.Value, err = cvt.ConvertValue(nv.Value)
   370  	stmt.isBatch = cvt.isBatch
   371  	return err
   372  }
   373  
   374  func (stmt *DmStatement) exec(args []driver.Value) (*DmResult, error) {
   375  	var err error
   376  
   377  	stmt.inUse = true
   378  	if stmt.isBatch && len(args) > 0 {
   379  		var tmpArg []driver.Value
   380  		var arg driver.Value
   381  		for i := len(args) - 1; i >= 0; i-- {
   382  			if args[i] != nil {
   383  				arg = args[i]
   384  				break
   385  			}
   386  		}
   387  		for _, row := range arg.([][]interface{}) {
   388  			tmpArg = append(tmpArg, row)
   389  		}
   390  		err = stmt.executeBatch(tmpArg)
   391  	} else {
   392  		err = stmt.executeInner(args, Dm_build_687)
   393  	}
   394  	if err != nil {
   395  		return nil, err
   396  	}
   397  	return newDmResult(stmt, stmt.execInfo), nil
   398  }
   399  
   400  func (stmt *DmStatement) execContext(ctx context.Context, args []driver.NamedValue) (*DmResult, error) {
   401  	stmt.inUse = true
   402  	dargs, err := namedValueToValue(stmt, args)
   403  	if err != nil {
   404  		return nil, err
   405  	}
   406  
   407  	if err := stmt.dmConn.watchCancel(ctx); err != nil {
   408  		return nil, err
   409  	}
   410  	defer stmt.dmConn.finish()
   411  
   412  	return stmt.exec(dargs)
   413  }
   414  
   415  func (stmt *DmStatement) query(args []driver.Value) (*DmRows, error) {
   416  	var err error
   417  	stmt.inUse = true
   418  	err = stmt.executeInner(args, Dm_build_686)
   419  	if err != nil {
   420  		return nil, err
   421  	}
   422  
   423  	return newDmRows(newInnerRows(0, stmt, stmt.execInfo)), nil
   424  }
   425  
   426  func (stmt *DmStatement) queryContext(ctx context.Context, args []driver.NamedValue) (*DmRows, error) {
   427  	stmt.inUse = true
   428  	dargs, err := namedValueToValue(stmt, args)
   429  	if err != nil {
   430  		return nil, err
   431  	}
   432  
   433  	if err := stmt.dmConn.watchCancel(ctx); err != nil {
   434  		return nil, err
   435  	}
   436  
   437  	rows, err := stmt.query(dargs)
   438  	if err != nil {
   439  		stmt.dmConn.finish()
   440  		return nil, err
   441  	}
   442  	rows.finish = stmt.dmConn.finish
   443  	return rows, err
   444  }
   445  
   446  func NewDmStmt(conn *DmConnection, sql string) (*DmStatement, error) {
   447  	var s *DmStatement
   448  
   449  	if conn.stmtMap != nil && len(conn.stmtMap) > 0 {
   450  		for _, sv := range conn.stmtMap {
   451  			if !sv.inUse {
   452  				sv.inUse = true
   453  				sv.nativeSql = sql
   454  				s = sv
   455  				break
   456  			}
   457  		}
   458  	}
   459  
   460  	if s == nil {
   461  		s = new(DmStatement)
   462  		s.resetFilterable(&conn.filterable)
   463  		s.objId = -1
   464  		s.idGenerator = dmStmtIDGenerator
   465  		s.dmConn = conn
   466  		s.maxRows = int64(conn.dmConnector.maxRows)
   467  		s.nativeSql = sql
   468  		s.rsMap = make(map[int16]*innerRows)
   469  		s.inUse = true
   470  		s.isBatch = conn.isBatch
   471  
   472  		if conn.stmtPool != nil && len(conn.stmtPool) > 0 {
   473  			len := len(conn.stmtPool)
   474  			spi := conn.stmtPool[0]
   475  			copy(conn.stmtPool, conn.stmtPool[1:])
   476  			conn.stmtPool = conn.stmtPool[:len-1]
   477  			s.id = spi.id
   478  			s.cursorName = spi.cursorName
   479  			s.readBaseColName = spi.readBaseColName
   480  		} else {
   481  			err := conn.Access.Dm_build_389(s)
   482  			if err != nil {
   483  				return nil, err
   484  			}
   485  		}
   486  		conn.stmtMap[s.id] = s
   487  	}
   488  
   489  	return s, nil
   490  
   491  }
   492  
   493  func (stmt *DmStatement) checkClosed() error {
   494  	if stmt.dmConn.closed.IsSet() {
   495  		return driver.ErrBadConn
   496  	} else if stmt.closed {
   497  		return ECGO_STATEMENT_HANDLE_CLOSED.throw()
   498  	}
   499  
   500  	return nil
   501  }
   502  
   503  func (stmt *DmStatement) pool() {
   504  	for _, rs := range stmt.rsMap {
   505  		rs.Close()
   506  	}
   507  
   508  	stmt.dmConn.stmtPool = append(stmt.dmConn.stmtPool, stmtPoolInfo{stmt.id, stmt.cursorName, stmt.readBaseColName})
   509  	delete(stmt.dmConn.stmtMap, stmt.id)
   510  	stmt.inUse = false
   511  	stmt.closed = true
   512  }
   513  
   514  func (stmt *DmStatement) free() error {
   515  	for _, rs := range stmt.rsMap {
   516  		rs.Close()
   517  	}
   518  
   519  	err := stmt.dmConn.Access.Dm_build_394(int32(stmt.id))
   520  	if err != nil {
   521  		return err
   522  	}
   523  	delete(stmt.dmConn.stmtMap, stmt.id)
   524  	stmt.inUse = false
   525  	stmt.closed = true
   526  	return nil
   527  }
   528  
   529  func encodeArgs(stmt *DmStatement, args []driver.Value) ([]interface{}, error) {
   530  	bytes := make([]interface{}, len(args), len(args))
   531  
   532  	var err error
   533  
   534  	for i, arg := range args {
   535  	nextSwitch:
   536  		if stmt.params[i].colType == CURSOR {
   537  			if stmt.params[i].cursorStmt == nil {
   538  				stmt.params[i].cursorStmt = &DmStatement{dmConn: stmt.dmConn}
   539  				stmt.params[i].cursorStmt.resetFilterable(&stmt.dmConn.filterable)
   540  				err = stmt.params[i].cursorStmt.dmConn.Access.Dm_build_389(stmt.params[i].cursorStmt)
   541  			}
   542  			stmt.curRowBindIndicator[i] |= BIND_OUT
   543  			continue
   544  		}
   545  		if arg == nil {
   546  			if resetColType(stmt, i, NULL) {
   547  				bytes[i] = ParamDataEnum_Null
   548  			}
   549  			continue
   550  		}
   551  
   552  		switch v := arg.(type) {
   553  		case bool:
   554  			if resetColType(stmt, i, BIT) {
   555  				bytes[i], err = G2DB.fromBool(v, stmt.params[i], stmt.dmConn)
   556  			}
   557  		case int8:
   558  			if resetColType(stmt, i, TINYINT) {
   559  				bytes[i], err = G2DB.fromInt64(int64(v), stmt.params[i], stmt.dmConn)
   560  			}
   561  		case int16:
   562  			if resetColType(stmt, i, SMALLINT) {
   563  				bytes[i], err = G2DB.fromInt64(int64(v), stmt.params[i], stmt.dmConn)
   564  			}
   565  		case int32:
   566  			if resetColType(stmt, i, INT) {
   567  				bytes[i], err = G2DB.fromInt64(int64(v), stmt.params[i], stmt.dmConn)
   568  			}
   569  		case int64:
   570  			if resetColType(stmt, i, BIGINT) {
   571  				bytes[i], err = G2DB.fromInt64(int64(v), stmt.params[i], stmt.dmConn)
   572  			}
   573  		case int:
   574  			if resetColType(stmt, i, BIGINT) {
   575  				bytes[i], err = G2DB.fromInt64(int64(v), stmt.params[i], stmt.dmConn)
   576  			}
   577  		case uint8:
   578  			if resetColType(stmt, i, SMALLINT) {
   579  				bytes[i], err = G2DB.fromInt64(int64(v), stmt.params[i], stmt.dmConn)
   580  			}
   581  		case uint16:
   582  			if resetColType(stmt, i, INT) {
   583  				bytes[i], err = G2DB.fromInt64(int64(v), stmt.params[i], stmt.dmConn)
   584  			}
   585  		case uint32:
   586  			if resetColType(stmt, i, BIGINT) {
   587  				bytes[i], err = G2DB.fromInt64(int64(v), stmt.params[i], stmt.dmConn)
   588  			}
   589  
   590  		case float32:
   591  			if resetColType(stmt, i, REAL) {
   592  				bytes[i], err = G2DB.fromFloat32(v, stmt.params[i], stmt.dmConn)
   593  			}
   594  		case float64:
   595  			if resetColType(stmt, i, DOUBLE) {
   596  				bytes[i], err = G2DB.fromFloat64(float64(v), stmt.params[i], stmt.dmConn)
   597  			}
   598  		case []byte:
   599  			if resetColType(stmt, i, VARBINARY) {
   600  				bytes[i], err = G2DB.fromBytes(v, stmt.params[i], stmt.dmConn)
   601  			}
   602  		case string:
   603  
   604  			if v == "" && emptyStringToNil(stmt.params[i].colType) {
   605  				arg = nil
   606  				goto nextSwitch
   607  			}
   608  			if resetColType(stmt, i, VARCHAR) {
   609  				bytes[i], err = G2DB.fromString(v, stmt.params[i], stmt.dmConn)
   610  			}
   611  		case time.Time:
   612  			if resetColType(stmt, i, DATETIME_TZ) {
   613  				bytes[i], err = G2DB.fromTime(v, stmt.params[i], stmt.dmConn)
   614  			}
   615  		case DmTimestamp:
   616  			if resetColType(stmt, i, DATETIME_TZ) {
   617  				bytes[i], err = G2DB.fromTime(v.ToTime(), stmt.params[i], stmt.dmConn)
   618  			}
   619  		case DmIntervalDT:
   620  			if resetColType(stmt, i, INTERVAL_DT) {
   621  				bytes[i], err = G2DB.fromDmIntervalDT(v, stmt.params[i], stmt.dmConn)
   622  			}
   623  		case DmIntervalYM:
   624  			if resetColType(stmt, i, INTERVAL_YM) {
   625  				bytes[i], err = G2DB.fromDmdbIntervalYM(v, stmt.params[i], stmt.dmConn)
   626  			}
   627  		case DmDecimal:
   628  			if resetColType(stmt, i, DECIMAL) {
   629  				bytes[i], err = G2DB.fromDecimal(v, stmt.params[i], stmt.dmConn)
   630  			}
   631  
   632  		case DmBlob:
   633  			if resetColType(stmt, i, BLOB) {
   634  				bytes[i], err = G2DB.fromBlob(DmBlob(v), stmt.params[i], stmt.dmConn)
   635  				if err != nil {
   636  					return nil, err
   637  				}
   638  			}
   639  		case DmClob:
   640  			if resetColType(stmt, i, CLOB) {
   641  				bytes[i], err = G2DB.fromClob(DmClob(v), stmt.params[i], stmt.dmConn)
   642  				if err != nil {
   643  					return nil, err
   644  				}
   645  			}
   646  		case DmArray:
   647  			if resetColType(stmt, i, ARRAY) {
   648  				da := &v
   649  				da, err = da.create(stmt.dmConn)
   650  				if err != nil {
   651  					return nil, err
   652  				}
   653  
   654  				bytes[i], err = G2DB.fromArray(da, stmt.params[i], stmt.dmConn)
   655  			}
   656  		case DmStruct:
   657  			if resetColType(stmt, i, RECORD) {
   658  				ds := &v
   659  				ds, err = ds.create(stmt.dmConn)
   660  				if err != nil {
   661  					return nil, err
   662  				}
   663  
   664  				bytes[i], err = G2DB.fromStruct(ds, stmt.params[i], stmt.dmConn)
   665  			}
   666  		case sql.Out:
   667  			arg = v.Dest
   668  			goto nextSwitch
   669  
   670  		case *DmTimestamp:
   671  			if resetColType(stmt, i, DATETIME_TZ) {
   672  				bytes[i], err = G2DB.fromTime(v.ToTime(), stmt.params[i], stmt.dmConn)
   673  			}
   674  		case *DmIntervalDT:
   675  			if resetColType(stmt, i, INTERVAL_DT) {
   676  				bytes[i], err = G2DB.fromDmIntervalDT(*v, stmt.params[i], stmt.dmConn)
   677  			}
   678  		case *DmIntervalYM:
   679  			if resetColType(stmt, i, INTERVAL_YM) {
   680  				bytes[i], err = G2DB.fromDmdbIntervalYM(*v, stmt.params[i], stmt.dmConn)
   681  			}
   682  		case *DmDecimal:
   683  			if resetColType(stmt, i, DECIMAL) {
   684  				bytes[i], err = G2DB.fromDecimal(*v, stmt.params[i], stmt.dmConn)
   685  			}
   686  		case *DmBlob:
   687  			if resetColType(stmt, i, BLOB) {
   688  				bytes[i], err = G2DB.fromBlob(DmBlob(*v), stmt.params[i], stmt.dmConn)
   689  			}
   690  		case *DmClob:
   691  			if resetColType(stmt, i, CLOB) {
   692  				bytes[i], err = G2DB.fromClob(DmClob(*v), stmt.params[i], stmt.dmConn)
   693  			}
   694  		case *DmArray:
   695  			if resetColType(stmt, i, ARRAY) {
   696  				v, err = v.create(stmt.dmConn)
   697  				if err != nil {
   698  					return nil, err
   699  				}
   700  
   701  				bytes[i], err = G2DB.fromArray(v, stmt.params[i], stmt.dmConn)
   702  			}
   703  		case *DmStruct:
   704  			if resetColType(stmt, i, RECORD) {
   705  				v, err = v.create(stmt.dmConn)
   706  				if err != nil {
   707  					return nil, err
   708  				}
   709  
   710  				bytes[i], err = G2DB.fromStruct(v, stmt.params[i], stmt.dmConn)
   711  			}
   712  		case *driver.Rows:
   713  			if stmt.params[i].colType == CURSOR && !resetColType(stmt, i, CURSOR) && stmt.params[i].cursorStmt == nil {
   714  				stmt.params[i].cursorStmt = &DmStatement{dmConn: stmt.dmConn}
   715  				stmt.params[i].cursorStmt.resetFilterable(&stmt.dmConn.filterable)
   716  				err = stmt.params[i].cursorStmt.dmConn.Access.Dm_build_389(stmt.params[i].cursorStmt)
   717  			}
   718  		case io.Reader:
   719  			bytes[i], err = G2DB.fromReader(io.Reader(v), stmt.params[i], stmt.dmConn)
   720  			if err != nil {
   721  				return nil, err
   722  			}
   723  		default:
   724  			err = ECGO_UNSUPPORTED_INPARAM_TYPE.throw()
   725  		}
   726  
   727  		if err != nil {
   728  			return nil, err
   729  		}
   730  
   731  	}
   732  
   733  	return bytes, nil
   734  }
   735  
   736  type converter struct {
   737  	conn    *DmConnection
   738  	isBatch bool
   739  }
   740  type decimalDecompose interface {
   741  	Decompose(buf []byte) (form byte, negative bool, coefficient []byte, exponent int32)
   742  }
   743  
   744  func (c *converter) ConvertValue(v interface{}) (driver.Value, error) {
   745  	if driver.IsValue(v) {
   746  		return v, nil
   747  	}
   748  
   749  	switch vr := v.(type) {
   750  	case driver.Valuer:
   751  		sv, err := callValuerValue(vr)
   752  		if err != nil {
   753  			return nil, err
   754  		}
   755  
   756  		return sv, nil
   757  
   758  	case decimalDecompose, DmDecimal, *DmDecimal, DmTimestamp, *DmTimestamp, DmIntervalDT, *DmIntervalDT,
   759  		DmIntervalYM, *DmIntervalYM, driver.Rows, *driver.Rows, DmArray, *DmArray, DmStruct, *DmStruct, sql.Out:
   760  		return vr, nil
   761  	case big.Int:
   762  		return NewDecimalFromBigInt(&vr)
   763  	case big.Float:
   764  		return NewDecimalFromBigFloat(&vr)
   765  	case DmClob:
   766  
   767  		if vr.connection == nil {
   768  			vr.connection = c.conn
   769  		}
   770  		return vr, nil
   771  	case DmBlob:
   772  
   773  		if vr.connection == nil {
   774  			vr.connection = c.conn
   775  		}
   776  		return vr, nil
   777  	case *DmBlob:
   778  
   779  		if vr.connection == nil {
   780  			vr.connection = c.conn
   781  		}
   782  		return vr, nil
   783  	case io.Reader:
   784  		return vr, nil
   785  	}
   786  
   787  	rv := reflect.ValueOf(v)
   788  	switch rv.Kind() {
   789  	case reflect.Ptr:
   790  		if rv.IsNil() {
   791  			return nil, nil
   792  		} else {
   793  			return c.ConvertValue(rv.Elem().Interface())
   794  		}
   795  	case reflect.Int:
   796  		return rv.Int(), nil
   797  	case reflect.Int8:
   798  		return int8(rv.Int()), nil
   799  	case reflect.Int16:
   800  		return int16(rv.Int()), nil
   801  	case reflect.Int32:
   802  		return int32(rv.Int()), nil
   803  	case reflect.Int64:
   804  		return int64(rv.Int()), nil
   805  	case reflect.Uint8:
   806  		return uint8(rv.Uint()), nil
   807  	case reflect.Uint16:
   808  		return uint16(rv.Uint()), nil
   809  	case reflect.Uint32:
   810  		return uint32(rv.Uint()), nil
   811  	case reflect.Uint64, reflect.Uint:
   812  		u64 := rv.Uint()
   813  		if u64 >= 1<<63 {
   814  			bigInt := &big.Int{}
   815  			bigInt.SetString(strconv.FormatUint(u64, 10), 10)
   816  			return NewDecimalFromBigInt(bigInt)
   817  		}
   818  		return int64(u64), nil
   819  	case reflect.Float32:
   820  		return float32(rv.Float()), nil
   821  	case reflect.Float64:
   822  		return float64(rv.Float()), nil
   823  	case reflect.Bool:
   824  		return rv.Bool(), nil
   825  	case reflect.Slice:
   826  		ek := rv.Type().Elem().Kind()
   827  		if ek == reflect.Uint8 {
   828  			return rv.Bytes(), nil
   829  		} else if ek == reflect.Slice {
   830  			c.isBatch = true
   831  			return v, nil
   832  		}
   833  		return nil, fmt.Errorf("unsupported type %T, a slice of %s", v, ek)
   834  	case reflect.String:
   835  		return rv.String(), nil
   836  	}
   837  	return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
   838  }
   839  
   840  var valuerReflectType = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
   841  
   842  func callValuerValue(vr driver.Valuer) (v driver.Value, err error) {
   843  	if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Ptr &&
   844  		rv.IsNil() &&
   845  		rv.Type().Elem().Implements(valuerReflectType) {
   846  		return nil, nil
   847  	}
   848  	return vr.Value()
   849  }
   850  
   851  func namedValueToValue(stmt *DmStatement, named []driver.NamedValue) ([]driver.Value, error) {
   852  
   853  	dargs := make([]driver.Value, stmt.paramCount)
   854  	for i, _ := range dargs {
   855  		found := false
   856  		for _, nv := range named {
   857  			if nv.Name != "" && strings.ToUpper(nv.Name) == strings.ToUpper(stmt.params[i].name) {
   858  				dargs[i] = nv.Value
   859  				found = true
   860  				break
   861  			}
   862  		}
   863  
   864  		if !found && i < len(named) {
   865  			dargs[i] = named[i].Value
   866  		}
   867  
   868  	}
   869  	return dargs, nil
   870  }
   871  
   872  func (stmt *DmStatement) executeInner(args []driver.Value, executeType int16) (err error) {
   873  
   874  	var bytes []interface{}
   875  
   876  	if stmt.paramCount > 0 {
   877  		bytes, err = encodeArgs(stmt, args)
   878  		if err != nil {
   879  			return err
   880  		}
   881  	}
   882  	stmt.execInfo, err = stmt.dmConn.Access.Dm_build_439(stmt, bytes, false)
   883  	if err != nil {
   884  		return err
   885  	}
   886  	if stmt.execInfo.outParamDatas != nil {
   887  		for i, outParamData := range stmt.execInfo.outParamDatas {
   888  			if stmt.curRowBindIndicator[i]&BIND_OUT == BIND_OUT {
   889  				if outParamData == nil {
   890  					if arg, ok := args[i].(*driver.Rows); ok && stmt.params[i].colType == CURSOR {
   891  						var tmpExecInfo *execRetInfo
   892  						if tmpExecInfo, err = stmt.dmConn.Access.Dm_build_449(stmt.params[i].cursorStmt, 1); err != nil {
   893  							return err
   894  						}
   895  						if tmpExecInfo.hasResultSet {
   896  							*arg = newDmRows(newInnerRows(0, stmt.params[i].cursorStmt, tmpExecInfo))
   897  						} else {
   898  							*arg = nil
   899  						}
   900  					} else {
   901  						args[i] = nil
   902  					}
   903  					continue
   904  				}
   905  				if args[i] == nil {
   906  					switch stmt.params[i].colType {
   907  					case BOOLEAN:
   908  						args[i], err = DB2G.toBool(outParamData, &stmt.params[i].column, stmt.dmConn)
   909  					case BIT:
   910  						if strings.ToLower(stmt.params[i].typeName) == "boolean" {
   911  							args[i], err = DB2G.toBool(outParamData, &stmt.params[i].column, stmt.dmConn)
   912  						}
   913  
   914  						args[i], err = DB2G.toInt8(outParamData, &stmt.params[i].column, stmt.dmConn)
   915  					case TINYINT:
   916  						args[i], err = DB2G.toInt8(outParamData, &stmt.params[i].column, stmt.dmConn)
   917  					case SMALLINT:
   918  						args[i], err = DB2G.toInt16(outParamData, &stmt.params[i].column, stmt.dmConn)
   919  					case INT:
   920  						args[i], err = DB2G.toInt32(outParamData, &stmt.params[i].column, stmt.dmConn)
   921  					case BIGINT:
   922  						args[i], err = DB2G.toInt64(outParamData, &stmt.params[i].column, stmt.dmConn)
   923  					case REAL:
   924  						args[i], err = DB2G.toFloat32(outParamData, &stmt.params[i].column, stmt.dmConn)
   925  					case DOUBLE:
   926  						args[i], err = DB2G.toFloat64(outParamData, &stmt.params[i].column, stmt.dmConn)
   927  					case DATE, TIME, DATETIME, TIME_TZ, DATETIME_TZ:
   928  						args[i], err = DB2G.toTime(outParamData, &stmt.params[i].column, stmt.dmConn)
   929  					case INTERVAL_DT:
   930  						args[i] = newDmIntervalDTByBytes(outParamData)
   931  					case INTERVAL_YM:
   932  						args[i] = newDmIntervalYMByBytes(outParamData)
   933  					case DECIMAL:
   934  						args[i], err = DB2G.toDmDecimal(outParamData, &stmt.params[i].column, stmt.dmConn)
   935  					case BINARY, VARBINARY:
   936  						args[i] = util.StringUtil.BytesToHexString(outParamData, false)
   937  					case BLOB:
   938  						args[i] = DB2G.toDmBlob(outParamData, &stmt.params[i].column, stmt.dmConn)
   939  					case CHAR, VARCHAR2, VARCHAR:
   940  						args[i] = DB2G.toString(outParamData, &stmt.params[i].column, stmt.dmConn)
   941  					case CLOB:
   942  						args[i] = DB2G.toDmClob(outParamData, stmt.dmConn, &stmt.params[i].column)
   943  					default:
   944  						err = ECGO_UNSUPPORTED_OUTPARAM_TYPE.throw()
   945  					}
   946  				} else {
   947  				nextSwitch:
   948  					switch v := args[i].(type) {
   949  					case sql.Out:
   950  						args[i] = v.Dest
   951  						goto nextSwitch
   952  					case string, *string:
   953  						args[i] = DB2G.toString(outParamData, &stmt.params[i].column, stmt.dmConn)
   954  					case []byte, *[]byte:
   955  						args[i], err = DB2G.toBytes(outParamData, &stmt.params[i].column, stmt.dmConn)
   956  					case bool, *bool:
   957  						args[i], err = DB2G.toBool(outParamData, &stmt.params[i].column, stmt.dmConn)
   958  					case int8, *int8:
   959  						args[i], err = DB2G.toInt8(outParamData, &stmt.params[i].column, stmt.dmConn)
   960  					case int16, *int16:
   961  						args[i], err = DB2G.toInt16(outParamData, &stmt.params[i].column, stmt.dmConn)
   962  					case int32, *int32:
   963  						args[i], err = DB2G.toInt32(outParamData, &stmt.params[i].column, stmt.dmConn)
   964  					case int64, *int64:
   965  						args[i], err = DB2G.toInt64(outParamData, &stmt.params[i].column, stmt.dmConn)
   966  					case uint8, *uint8:
   967  						args[i], err = DB2G.toByte(outParamData, &stmt.params[i].column, stmt.dmConn)
   968  					case uint16, *uint16:
   969  						args[i], err = DB2G.toUInt16(outParamData, &stmt.params[i].column, stmt.dmConn)
   970  					case uint32, *uint32:
   971  						args[i], err = DB2G.toUInt32(outParamData, &stmt.params[i].column, stmt.dmConn)
   972  					case uint64, *uint64:
   973  						args[i], err = DB2G.toUInt64(outParamData, &stmt.params[i].column, stmt.dmConn)
   974  					case int, *int:
   975  						args[i], err = DB2G.toInt(outParamData, &stmt.params[i].column, stmt.dmConn)
   976  					case uint, *uint:
   977  						args[i], err = DB2G.toUInt(outParamData, &stmt.params[i].column, stmt.dmConn)
   978  					case float32, *float32:
   979  						args[i], err = DB2G.toFloat32(outParamData, &stmt.params[i].column, stmt.dmConn)
   980  					case float64, *float64:
   981  						args[i], err = DB2G.toFloat64(outParamData, &stmt.params[i].column, stmt.dmConn)
   982  					case time.Time, *time.Time:
   983  						args[i], err = DB2G.toTime(outParamData, &stmt.params[i].column, stmt.dmConn)
   984  					case DmTimestamp, *DmTimestamp:
   985  						args[i] = newDmTimestampFromBytes(outParamData, stmt.params[i].column, stmt.dmConn)
   986  					case DmIntervalDT, *DmIntervalDT:
   987  						args[i] = newDmIntervalDTByBytes(outParamData)
   988  					case DmIntervalYM, *DmIntervalYM:
   989  						args[i] = newDmIntervalYMByBytes(outParamData)
   990  					case DmDecimal, *DmDecimal:
   991  						args[i], err = DB2G.toDmDecimal(outParamData, &stmt.params[i].column, stmt.dmConn)
   992  					case DmBlob, *DmBlob:
   993  						args[i] = DB2G.toDmBlob(outParamData, &stmt.params[i].column, stmt.dmConn)
   994  					case DmClob, *DmClob:
   995  						args[i] = DB2G.toDmClob(outParamData, stmt.dmConn, &stmt.params[i].column)
   996  					case *driver.Rows:
   997  						if stmt.params[i].colType == CURSOR {
   998  							var tmpExecInfo *execRetInfo
   999  							tmpExecInfo, err = stmt.dmConn.Access.Dm_build_449(stmt.params[i].cursorStmt, 1)
  1000  							if err != nil {
  1001  								return err
  1002  							}
  1003  
  1004  							if tmpExecInfo.hasResultSet {
  1005  								*v = newDmRows(newInnerRows(0, stmt.params[i].cursorStmt, tmpExecInfo))
  1006  							} else {
  1007  								*v = nil
  1008  							}
  1009  						}
  1010  					case DmArray, *DmArray:
  1011  						args[i], err = TypeDataSV.bytesToArray(outParamData, nil, stmt.params[i].typeDescriptor)
  1012  					case DmStruct, *DmStruct:
  1013  						args[i], err = TypeDataSV.bytesToRecord(outParamData, nil, stmt.params[i].typeDescriptor)
  1014  					default:
  1015  						err = ECGO_UNSUPPORTED_OUTPARAM_TYPE.throw()
  1016  					}
  1017  				}
  1018  			}
  1019  		}
  1020  	}
  1021  
  1022  	return err
  1023  }
  1024  
  1025  func (stmt *DmStatement) executeBatch(args []driver.Value) (err error) {
  1026  
  1027  	var bytes [][]interface{}
  1028  
  1029  	if stmt.execInfo.retSqlType == Dm_build_700 || stmt.execInfo.retSqlType == Dm_build_705 {
  1030  		return ECGO_INVALID_SQL_TYPE.throw()
  1031  	}
  1032  
  1033  	if stmt.paramCount > 0 && args != nil && len(args) > 0 {
  1034  
  1035  		if len(args) == 1 || stmt.dmConn.dmConnector.batchType == 2 ||
  1036  			(stmt.dmConn.dmConnector.batchNotOnCall && stmt.execInfo.retSqlType == Dm_build_701) {
  1037  			return stmt.executeBatchByRow(args)
  1038  		} else {
  1039  			for _, arg := range args {
  1040  				var newArg []driver.Value
  1041  				for _, a := range arg.([]interface{}) {
  1042  					newArg = append(newArg, a)
  1043  				}
  1044  				tmpBytes, err := encodeArgs(stmt, newArg)
  1045  				if err != nil {
  1046  					return err
  1047  				}
  1048  				bytes = append(bytes, tmpBytes)
  1049  			}
  1050  			stmt.execInfo, err = stmt.dmConn.Access.Dm_build_428(stmt, bytes, stmt.preExec)
  1051  		}
  1052  	}
  1053  	return err
  1054  }
  1055  
  1056  func (stmt *DmStatement) executeBatchByRow(args []driver.Value) (err error) {
  1057  	count := len(args)
  1058  	stmt.execInfo = NewExceInfo()
  1059  	stmt.execInfo.updateCounts = make([]int64, count)
  1060  	var sqlErrBuilder strings.Builder
  1061  	for i := 0; i < count; i++ {
  1062  		tmpExecInfo, err := stmt.dmConn.Access.Dm_build_439(stmt, args[i].([]interface{}), stmt.preExec || i != 0)
  1063  		if err == nil {
  1064  			stmt.execInfo.union(tmpExecInfo, i, 1)
  1065  		} else {
  1066  			stmt.execInfo.updateCounts[i] = -1
  1067  			if stmt.dmConn.dmConnector.continueBatchOnError {
  1068  				sqlErrBuilder.WriteString("row[" + strconv.Itoa(i) + "]:" + err.Error() + util.LINE_SEPARATOR)
  1069  			} else {
  1070  				return ECGO_BATCH_ERROR.addDetailln(err.Error()).throw()
  1071  			}
  1072  		}
  1073  	}
  1074  	if sqlErrBuilder.Len() > 0 {
  1075  		return EC_BP_WITH_ERROR.addDetail(sqlErrBuilder.String()).throw()
  1076  	}
  1077  	return nil
  1078  }