gitee.com/chunanyong/dm@v1.8.12/u.go (about)

     1  /*
     2   * Copyright (c) 2000-2018, 达梦数据库有限公司.
     3   * All rights reserved.
     4   */
     5  package dm
     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  	"gitee.com/chunanyong/dm/util"
    21  )
    22  
    23  var rp = newRsPool()
    24  
    25  type DmStatement struct {
    26  	filterable
    27  
    28  	dmConn *DmConnection
    29  	rsMap  map[int16]*innerRows
    30  	inUse  bool
    31  
    32  	prepared  bool
    33  	innerUsed bool
    34  
    35  	innerExec bool
    36  
    37  	id int32
    38  
    39  	cursorName string
    40  
    41  	readBaseColName bool
    42  
    43  	execInfo *execRetInfo
    44  
    45  	resultSetType int
    46  
    47  	resultSetConcurrency int
    48  
    49  	resultSetHoldability int
    50  
    51  	nativeSql string
    52  
    53  	maxFieldSize int
    54  
    55  	maxRows int64
    56  
    57  	escapeProcessing bool
    58  
    59  	queryTimeout int32
    60  
    61  	fetchDirection int
    62  
    63  	fetchSize int
    64  
    65  	cursorUpdateRow int64
    66  
    67  	closeOnCompletion bool
    68  
    69  	isBatch bool
    70  
    71  	closed bool
    72  
    73  	columns []column
    74  
    75  	serverParams []parameter
    76  
    77  	bindParams []parameter
    78  
    79  	paramCount int32
    80  
    81  	preExec bool
    82  }
    83  
    84  type stmtPoolInfo struct {
    85  	id int32
    86  
    87  	cursorName string
    88  
    89  	readBaseColName bool
    90  }
    91  
    92  type rsPoolKey struct {
    93  	dbGuid        string
    94  	currentSchema string
    95  	sql           string
    96  	paramCount    int
    97  }
    98  
    99  func newRsPoolKey(stmt *DmStatement, sql string) rsPoolKey {
   100  	rpk := new(rsPoolKey)
   101  	rpk.dbGuid = stmt.dmConn.Guid
   102  	rpk.currentSchema = stmt.dmConn.Schema
   103  	rpk.paramCount = int(stmt.paramCount)
   104  
   105  	rpk.sql = sql
   106  	return *rpk
   107  }
   108  
   109  func (key rsPoolKey) equals(destKey rsPoolKey) bool {
   110  	return key.dbGuid == destKey.dbGuid &&
   111  		key.currentSchema == destKey.currentSchema &&
   112  		key.sql == destKey.sql &&
   113  		key.paramCount == destKey.paramCount
   114  
   115  }
   116  
   117  type rsPoolValue struct {
   118  	m_lastChkTime int
   119  	m_TbIds       []int32
   120  	m_TbTss       []int64
   121  	execInfo      *execRetInfo
   122  }
   123  
   124  func newRsPoolValue(execInfo *execRetInfo) rsPoolValue {
   125  	rpv := new(rsPoolValue)
   126  	rpv.execInfo = execInfo
   127  	rpv.m_lastChkTime = time.Now().Nanosecond()
   128  	copy(rpv.m_TbIds, execInfo.tbIds)
   129  	copy(rpv.m_TbTss, execInfo.tbTss)
   130  	return *rpv
   131  }
   132  
   133  func (rpv rsPoolValue) refreshed(conn *DmConnection) (bool, error) {
   134  
   135  	if conn.dmConnector.rsRefreshFreq == 0 {
   136  		return false, nil
   137  	}
   138  
   139  	if rpv.m_lastChkTime+conn.dmConnector.rsRefreshFreq*int(time.Second) > time.Now().Nanosecond() {
   140  		return false, nil
   141  	}
   142  
   143  	tss, err := conn.Access.Dm_build_1496(interface{}(rpv.m_TbIds).([]uint32))
   144  	if err != nil {
   145  		return false, err
   146  	}
   147  	rpv.m_lastChkTime = time.Now().Nanosecond()
   148  
   149  	var tbCount int
   150  	if tss != nil {
   151  		tbCount = len(tss)
   152  	}
   153  
   154  	if tbCount != len(rpv.m_TbTss) {
   155  		return true, nil
   156  	}
   157  
   158  	for i := 0; i < tbCount; i++ {
   159  		if rpv.m_TbTss[i] != tss[i] {
   160  			return true, nil
   161  		}
   162  
   163  	}
   164  	return false, nil
   165  }
   166  
   167  func (rpv rsPoolValue) getResultSet(stmt *DmStatement) *innerRows {
   168  	destDatas := rpv.execInfo.rsDatas
   169  	var totalRows int
   170  	if rpv.execInfo.rsDatas != nil {
   171  		totalRows = len(rpv.execInfo.rsDatas)
   172  	}
   173  
   174  	if stmt.maxRows > 0 && stmt.maxRows < int64(totalRows) {
   175  		destDatas = make([][][]byte, stmt.maxRows)
   176  		copy(destDatas[:len(destDatas)], rpv.execInfo.rsDatas[:len(destDatas)])
   177  	}
   178  
   179  	rs := newLocalInnerRows(stmt, stmt.columns, destDatas)
   180  	rs.id = 1
   181  	return rs
   182  }
   183  
   184  func (rpv rsPoolValue) getDataLen() int {
   185  	return rpv.execInfo.rsSizeof
   186  }
   187  
   188  type rsPool struct {
   189  	rsMap        map[rsPoolKey]rsPoolValue
   190  	rsList       *list.List
   191  	totalDataLen int
   192  }
   193  
   194  func newRsPool() *rsPool {
   195  	rp := new(rsPool)
   196  	rp.rsMap = make(map[rsPoolKey]rsPoolValue, 100)
   197  	rp.rsList = list.New()
   198  	return rp
   199  }
   200  
   201  func (rp *rsPool) removeInList(key rsPoolKey) {
   202  	for e := rp.rsList.Front(); e != nil && e.Value.(rsPoolKey).equals(key); e = e.Next() {
   203  		rp.rsList.Remove(e)
   204  	}
   205  }
   206  
   207  func (rp *rsPool) put(stmt *DmStatement, sql string, execInfo *execRetInfo) {
   208  	var dataLen int
   209  	if execInfo != nil {
   210  		dataLen = execInfo.rsSizeof
   211  	}
   212  
   213  	cacheSize := stmt.dmConn.dmConnector.rsCacheSize * 1024 * 1024
   214  
   215  	for rp.totalDataLen+dataLen > cacheSize {
   216  		if rp.totalDataLen == 0 {
   217  			return
   218  		}
   219  
   220  		lk := rp.rsList.Back().Value.(rsPoolKey)
   221  		rp.totalDataLen -= rp.rsMap[lk].getDataLen()
   222  		rp.rsList.Remove(rp.rsList.Back())
   223  		delete(rp.rsMap, rp.rsList.Back().Value.(rsPoolKey))
   224  	}
   225  
   226  	key := newRsPoolKey(stmt, sql)
   227  	value := newRsPoolValue(execInfo)
   228  
   229  	if _, ok := rp.rsMap[key]; !ok {
   230  		rp.rsList.PushFront(key)
   231  	} else {
   232  		rp.removeInList(key)
   233  		rp.rsList.PushFront(key)
   234  	}
   235  
   236  	rp.rsMap[key] = value
   237  	rp.totalDataLen += dataLen
   238  }
   239  
   240  func (rp *rsPool) get(stmt *DmStatement, sql string) (*rsPoolValue, error) {
   241  	key := newRsPoolKey(stmt, sql)
   242  
   243  	v, ok := rp.rsMap[key]
   244  	if ok {
   245  		b, err := v.refreshed(stmt.dmConn)
   246  		if err != nil {
   247  			return nil, err
   248  		}
   249  
   250  		if b {
   251  			rp.removeInList(key)
   252  			delete(rp.rsMap, key)
   253  			return nil, nil
   254  		}
   255  
   256  		rp.removeInList(key)
   257  		rp.rsList.PushFront(key)
   258  		return &v, nil
   259  	} else {
   260  		return nil, nil
   261  	}
   262  }
   263  
   264  func (s *DmStatement) Close() error {
   265  	if s.closed {
   266  		return nil
   267  	}
   268  	if len(s.filterChain.filters) == 0 {
   269  		return s.close()
   270  	}
   271  	return s.filterChain.reset().DmStatementClose(s)
   272  }
   273  
   274  func (s *DmStatement) NumInput() int {
   275  	if err := s.checkClosed(); err != nil {
   276  		return -1
   277  	}
   278  	if len(s.filterChain.filters) == 0 {
   279  		return s.numInput()
   280  	}
   281  	return s.filterChain.reset().DmStatementNumInput(s)
   282  }
   283  
   284  func (s *DmStatement) Exec(args []driver.Value) (driver.Result, error) {
   285  	if err := s.checkClosed(); err != nil {
   286  		return nil, err
   287  	}
   288  	if len(s.filterChain.filters) == 0 {
   289  		return s.exec(args)
   290  	}
   291  	return s.filterChain.reset().DmStatementExec(s, args)
   292  }
   293  
   294  func (s *DmStatement) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
   295  	if err := s.checkClosed(); err != nil {
   296  		return nil, err
   297  	}
   298  	if len(s.filterChain.filters) == 0 {
   299  		return s.execContext(ctx, args)
   300  	}
   301  	return s.filterChain.reset().DmStatementExecContext(s, ctx, args)
   302  }
   303  
   304  func (s *DmStatement) Query(args []driver.Value) (driver.Rows, error) {
   305  	if err := s.checkClosed(); err != nil {
   306  		return nil, err
   307  	}
   308  	if len(s.filterChain.filters) == 0 {
   309  		return s.query(args)
   310  	}
   311  	return s.filterChain.reset().DmStatementQuery(s, args)
   312  }
   313  
   314  func (s *DmStatement) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
   315  	if err := s.checkClosed(); err != nil {
   316  		return nil, err
   317  	}
   318  	if len(s.filterChain.filters) == 0 {
   319  		return s.queryContext(ctx, args)
   320  	}
   321  	return s.filterChain.reset().DmStatementQueryContext(s, ctx, args)
   322  }
   323  
   324  func (s *DmStatement) CheckNamedValue(nv *driver.NamedValue) error {
   325  	if len(s.filterChain.filters) == 0 {
   326  		return s.checkNamedValue(nv)
   327  	}
   328  	return s.filterChain.reset().DmStatementCheckNamedValue(s, nv)
   329  }
   330  
   331  func (st *DmStatement) prepare() error {
   332  	var err error
   333  	if st.dmConn.dmConnector.escapeProcess {
   334  		st.nativeSql, err = st.dmConn.escape(st.nativeSql, st.dmConn.dmConnector.keyWords)
   335  		if err != nil {
   336  			return err
   337  		}
   338  	}
   339  
   340  	st.execInfo, err = st.dmConn.Access.Dm_build_1421(st, Dm_build_95)
   341  	if err != nil {
   342  		return err
   343  	}
   344  	st.prepared = true
   345  	return nil
   346  }
   347  
   348  func (stmt *DmStatement) close() error {
   349  	delete(stmt.dmConn.stmtMap, stmt.id)
   350  	if stmt.closed {
   351  		return nil
   352  	}
   353  	stmt.inUse = true
   354  
   355  	return stmt.free()
   356  
   357  }
   358  
   359  func (stmt *DmStatement) numInput() int {
   360  	return int(stmt.paramCount)
   361  }
   362  
   363  func (stmt *DmStatement) checkNamedValue(nv *driver.NamedValue) error {
   364  	var err error
   365  	var cvt = converter{stmt.dmConn, false}
   366  	nv.Value, err = cvt.ConvertValue(nv.Value)
   367  	stmt.isBatch = cvt.isBatch
   368  	return err
   369  }
   370  
   371  func (stmt *DmStatement) exec(args []driver.Value) (*DmResult, error) {
   372  	var err error
   373  
   374  	stmt.inUse = true
   375  	if stmt.isBatch && len(args) > 0 {
   376  		var tmpArg []driver.Value
   377  		var arg driver.Value
   378  		for i := len(args) - 1; i >= 0; i-- {
   379  			if args[i] != nil {
   380  				arg = args[i]
   381  				break
   382  			}
   383  		}
   384  		for _, row := range arg.([][]interface{}) {
   385  			tmpArg = append(tmpArg, row)
   386  		}
   387  		err = stmt.executeBatch(tmpArg)
   388  	} else {
   389  		err = stmt.executeInner(args, Dm_build_97)
   390  	}
   391  	if err != nil {
   392  		return nil, err
   393  	}
   394  	return newDmResult(stmt, stmt.execInfo), nil
   395  }
   396  
   397  func (stmt *DmStatement) execContext(ctx context.Context, args []driver.NamedValue) (*DmResult, error) {
   398  	stmt.inUse = true
   399  	dargs, err := namedValueToValue(stmt, args)
   400  	if err != nil {
   401  		return nil, err
   402  	}
   403  
   404  	if err := stmt.dmConn.watchCancel(ctx); err != nil {
   405  		return nil, err
   406  	}
   407  	defer stmt.dmConn.finish()
   408  
   409  	return stmt.exec(dargs)
   410  }
   411  
   412  func (stmt *DmStatement) query(args []driver.Value) (*DmRows, error) {
   413  	var err error
   414  	stmt.inUse = true
   415  	err = stmt.executeInner(args, Dm_build_96)
   416  	if err != nil {
   417  		return nil, err
   418  	}
   419  
   420  	if stmt.execInfo.hasResultSet {
   421  		return newDmRows(newInnerRows(0, stmt, stmt.execInfo)), nil
   422  	} else {
   423  		return newDmRows(newLocalInnerRows(stmt, nil, nil)), nil
   424  	}
   425  }
   426  
   427  func (stmt *DmStatement) queryContext(ctx context.Context, args []driver.NamedValue) (*DmRows, error) {
   428  	stmt.inUse = true
   429  	dargs, err := namedValueToValue(stmt, args)
   430  	if err != nil {
   431  		return nil, err
   432  	}
   433  
   434  	if err := stmt.dmConn.watchCancel(ctx); err != nil {
   435  		return nil, err
   436  	}
   437  	defer stmt.dmConn.finish()
   438  
   439  	rows, err := stmt.query(dargs)
   440  	if err != nil {
   441  		stmt.dmConn.finish()
   442  		return nil, err
   443  	}
   444  	rows.finish = stmt.dmConn.finish
   445  	return rows, err
   446  }
   447  
   448  func NewDmStmt(conn *DmConnection, sql string) (*DmStatement, error) {
   449  	var s *DmStatement
   450  
   451  	if s == nil {
   452  		s = new(DmStatement)
   453  		s.resetFilterable(&conn.filterable)
   454  		s.objId = -1
   455  		s.idGenerator = dmStmtIDGenerator
   456  		s.dmConn = conn
   457  		s.maxRows = int64(conn.dmConnector.maxRows)
   458  		s.nativeSql = sql
   459  		s.rsMap = make(map[int16]*innerRows)
   460  		s.inUse = true
   461  		s.isBatch = conn.isBatch
   462  
   463  		err := conn.Access.Dm_build_1403(s)
   464  		if err != nil {
   465  			return nil, err
   466  		}
   467  
   468  		conn.stmtMap[s.id] = s
   469  	}
   470  
   471  	return s, nil
   472  
   473  }
   474  
   475  func (stmt *DmStatement) checkClosed() error {
   476  	if stmt.dmConn.closed.IsSet() {
   477  		return driver.ErrBadConn
   478  	} else if stmt.closed {
   479  		return ECGO_STATEMENT_HANDLE_CLOSED.throw()
   480  	}
   481  
   482  	return nil
   483  }
   484  
   485  func (stmt *DmStatement) free() error {
   486  	delete(stmt.dmConn.stmtMap, stmt.id)
   487  	for _, rs := range stmt.rsMap {
   488  		rs.Close()
   489  	}
   490  
   491  	err := stmt.dmConn.Access.Dm_build_1408(int32(stmt.id))
   492  	if err != nil {
   493  		return err
   494  	}
   495  	stmt.inUse = false
   496  	stmt.closed = true
   497  	return nil
   498  }
   499  
   500  func bindInParam(stmt *DmStatement, i int, dtype int32, firstRow bool) {
   501  	if !firstRow {
   502  		return
   503  	}
   504  	isNil := dtype == NULL
   505  	serverParam := &stmt.serverParams[i]
   506  	bindParam := &stmt.bindParams[i]
   507  	if serverParam == nil {
   508  		bindParam.resetType(dtype)
   509  	} else {
   510  		bindParam.name = serverParam.name
   511  		bindParam.typeDescriptor = serverParam.typeDescriptor
   512  		bindParam.mask = serverParam.mask
   513  		bindParam.typeFlag = serverParam.typeFlag
   514  
   515  		if (serverParam.colType != UNKNOWN && (isNil || serverParam.typeFlag == TYPE_FLAG_EXACT)) || serverParam.mask != 0 {
   516  
   517  			bindParam.colType = serverParam.colType
   518  			bindParam.prec = serverParam.prec
   519  			bindParam.scale = serverParam.scale
   520  			bindParam.mask = serverParam.mask
   521  		} else {
   522  
   523  			bindParam.resetType(dtype)
   524  		}
   525  	}
   526  
   527  	if bindParam.ioType == IO_TYPE_OUT || bindParam.ioType == IO_TYPE_INOUT {
   528  		bindParam.ioType = IO_TYPE_INOUT
   529  	} else {
   530  		bindParam.ioType = IO_TYPE_IN
   531  	}
   532  }
   533  
   534  func checkBindParameters(stmt *DmStatement, bytes []interface{}) error {
   535  
   536  	for i := 0; int32(i) < stmt.paramCount; i++ {
   537  		if stmt.bindParams[i].ioType == IO_TYPE_UNKNOWN {
   538  
   539  			if stmt.serverParams[i].ioType == IO_TYPE_OUT {
   540  
   541  				bytes[i] = nil
   542  			} else {
   543  				return ECGO_UNBINDED_PARAMETER.throw()
   544  			}
   545  		}
   546  
   547  		if stmt.bindParams[i].colType == CURSOR {
   548  			stmt.bindParams[i].ioType = IO_TYPE_INOUT
   549  			continue
   550  		}
   551  
   552  		if stmt.serverParams[i].ioType != stmt.bindParams[i].ioType {
   553  
   554  			stmt.bindParams[i].ioType = stmt.serverParams[i].ioType
   555  		}
   556  	}
   557  
   558  	for i := 0; int32(i) < stmt.paramCount; i++ {
   559  		if stmt.bindParams[i].ioType == IO_TYPE_INOUT || stmt.bindParams[i].ioType == IO_TYPE_OUT {
   560  			continue
   561  		}
   562  		switch stmt.bindParams[i].colType {
   563  		case CHAR, VARCHAR, VARCHAR2:
   564  			length := -1
   565  			if b, ok := bytes[i].([]byte); ok {
   566  				length = len(b)
   567  			}
   568  			if length > VARCHAR_PREC {
   569  				return ECGO_STRING_CUT.throw()
   570  			}
   571  			if length > int(stmt.bindParams[i].prec) {
   572  				if length < VARCHAR_PREC/4 {
   573  					stmt.bindParams[i].prec = VARCHAR_PREC / 4
   574  				} else if length < VARCHAR_PREC/2 {
   575  					stmt.bindParams[i].prec = VARCHAR_PREC / 2
   576  				} else if length < VARCHAR_PREC*3/4 {
   577  					stmt.bindParams[i].prec = VARCHAR_PREC * 3 / 4
   578  				} else {
   579  					stmt.bindParams[i].prec = VARCHAR_PREC
   580  				}
   581  			}
   582  		}
   583  	}
   584  	return nil
   585  }
   586  
   587  func bindOutParam(stmt *DmStatement, i int, dtype int32) error {
   588  	var err error
   589  	serverParam := &stmt.serverParams[i]
   590  	bindParam := &stmt.bindParams[i]
   591  
   592  	if bindParam.ioType == IO_TYPE_OUT || bindParam.ioType == IO_TYPE_UNKNOWN {
   593  
   594  		if serverParam == nil {
   595  
   596  			bindParam.resetType(dtype)
   597  		} else {
   598  
   599  			bindParam.name = serverParam.name
   600  			bindParam.typeDescriptor = serverParam.typeDescriptor
   601  			bindParam.mask = serverParam.mask
   602  			bindParam.typeFlag = serverParam.typeFlag
   603  
   604  			if (serverParam.colType != UNKNOWN && serverParam.typeFlag == TYPE_FLAG_EXACT) || serverParam.mask != 0 {
   605  
   606  				bindParam.colType = serverParam.colType
   607  				bindParam.prec = serverParam.prec
   608  				bindParam.scale = serverParam.scale
   609  				bindParam.mask = serverParam.mask
   610  			} else {
   611  
   612  				bindParam.resetType(dtype)
   613  			}
   614  		}
   615  
   616  		if bindParam.colType == CURSOR {
   617  			bindParam.ioType = IO_TYPE_INOUT
   618  			if bindParam.cursorStmt == nil {
   619  				bindParam.cursorStmt = &DmStatement{dmConn: stmt.dmConn}
   620  				bindParam.cursorStmt.resetFilterable(&stmt.dmConn.filterable)
   621  				err = bindParam.cursorStmt.dmConn.Access.Dm_build_1403(bindParam.cursorStmt)
   622  			}
   623  		}
   624  	}
   625  
   626  	if bindParam.ioType == IO_TYPE_IN || bindParam.ioType == IO_TYPE_INOUT {
   627  		bindParam.ioType = IO_TYPE_INOUT
   628  	} else {
   629  		bindParam.ioType = IO_TYPE_OUT
   630  	}
   631  
   632  	return err
   633  }
   634  
   635  func encodeArgs(stmt *DmStatement, args []driver.Value, firstRow bool) ([]interface{}, error) {
   636  	bytes := make([]interface{}, len(args), len(args))
   637  
   638  	var err error
   639  
   640  	for i, arg := range args {
   641  	nextSwitch:
   642  		if stmt.serverParams[i].colType == CURSOR {
   643  			bindInParam(stmt, i, CURSOR, firstRow)
   644  			if stmt.bindParams[i].cursorStmt == nil {
   645  				stmt.bindParams[i].cursorStmt = &DmStatement{dmConn: stmt.dmConn}
   646  				stmt.bindParams[i].cursorStmt.resetFilterable(&stmt.dmConn.filterable)
   647  				err = stmt.bindParams[i].cursorStmt.dmConn.Access.Dm_build_1403(stmt.bindParams[i].cursorStmt)
   648  			}
   649  			stmt.bindParams[i].ioType = IO_TYPE_INOUT
   650  			continue
   651  		}
   652  		if arg == nil {
   653  			bindInParam(stmt, i, NULL, firstRow)
   654  			bytes[i] = nil
   655  
   656  			continue
   657  		}
   658  
   659  		switch v := arg.(type) {
   660  		case bool:
   661  			bindInParam(stmt, i, TINYINT, firstRow)
   662  			bytes[i], err = G2DB.fromBool(v, stmt.bindParams[i], stmt.dmConn)
   663  		case int8:
   664  			bindInParam(stmt, i, TINYINT, firstRow)
   665  			bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn)
   666  		case int16:
   667  			bindInParam(stmt, i, SMALLINT, firstRow)
   668  			bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn)
   669  		case int32:
   670  			bindInParam(stmt, i, INT, firstRow)
   671  			bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn)
   672  		case int64:
   673  			bindInParam(stmt, i, BIGINT, firstRow)
   674  			bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn)
   675  		case int:
   676  			bindInParam(stmt, i, BIGINT, firstRow)
   677  			bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn)
   678  		case uint8:
   679  			bindInParam(stmt, i, SMALLINT, firstRow)
   680  			bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn)
   681  		case uint16:
   682  			bindInParam(stmt, i, INT, firstRow)
   683  			bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn)
   684  		case uint32:
   685  			bindInParam(stmt, i, BIGINT, firstRow)
   686  			bytes[i], err = G2DB.fromInt64(int64(v), stmt.bindParams[i], stmt.dmConn)
   687  
   688  		case float32:
   689  			bindInParam(stmt, i, REAL, firstRow)
   690  			bytes[i], err = G2DB.fromFloat32(v, stmt.bindParams[i], stmt.dmConn)
   691  		case float64:
   692  			bindInParam(stmt, i, DOUBLE, firstRow)
   693  			bytes[i], err = G2DB.fromFloat64(float64(v), stmt.bindParams[i], stmt.dmConn)
   694  		case []byte:
   695  			if v == nil {
   696  				bindInParam(stmt, i, NULL, firstRow)
   697  				bytes[i] = nil
   698  
   699  			} else {
   700  				dtype := VARBINARY
   701  				if len(v) >= VARBINARY_PREC {
   702  					dtype = BLOB
   703  				}
   704  				bindInParam(stmt, i, int32(dtype), firstRow)
   705  				bytes[i], err = G2DB.fromBytes(v, stmt.bindParams[i], stmt.dmConn)
   706  			}
   707  		case string:
   708  
   709  			if v == "" && emptyStringToNil(stmt.serverParams[i].colType) {
   710  				arg = nil
   711  				goto nextSwitch
   712  			}
   713  			dtype := VARCHAR
   714  			if len(v) >= VARCHAR_PREC {
   715  				dtype = CLOB
   716  			}
   717  			bindInParam(stmt, i, int32(dtype), firstRow)
   718  			bytes[i], err = G2DB.fromString(v, stmt.bindParams[i], stmt.dmConn)
   719  		case time.Time:
   720  			bindInParam(stmt, i, DATETIME, firstRow)
   721  			bytes[i], err = G2DB.fromTime(v, stmt.bindParams[i], stmt.dmConn)
   722  		case DmTimestamp:
   723  			bindInParam(stmt, i, DATETIME, firstRow)
   724  			bytes[i], err = G2DB.fromTime(v.ToTime(), stmt.bindParams[i], stmt.dmConn)
   725  		case DmIntervalDT:
   726  			bindInParam(stmt, i, INTERVAL_DT, firstRow)
   727  			if stmt.bindParams[i].typeFlag != TYPE_FLAG_EXACT {
   728  				stmt.bindParams[i].scale = int32(v.scaleForSvr)
   729  			}
   730  			bytes[i], err = G2DB.fromDmIntervalDT(v, stmt.bindParams[i], stmt.dmConn)
   731  		case DmIntervalYM:
   732  			bindInParam(stmt, i, INTERVAL_YM, firstRow)
   733  			if stmt.bindParams[i].typeFlag != TYPE_FLAG_EXACT {
   734  				stmt.bindParams[i].scale = int32(v.scaleForSvr)
   735  			}
   736  			bytes[i], err = G2DB.fromDmdbIntervalYM(v, stmt.bindParams[i], stmt.dmConn)
   737  		case DmDecimal:
   738  			bindInParam(stmt, i, DECIMAL, firstRow)
   739  			bytes[i], err = G2DB.fromDecimal(v, stmt.bindParams[i], stmt.dmConn)
   740  
   741  		case DmBlob:
   742  			bindInParam(stmt, i, BLOB, firstRow)
   743  			bytes[i], err = G2DB.fromBlob(DmBlob(v), stmt.bindParams[i], stmt.dmConn)
   744  			if err != nil {
   745  				return nil, err
   746  			}
   747  		case DmClob:
   748  			bindInParam(stmt, i, CLOB, firstRow)
   749  			bytes[i], err = G2DB.fromClob(DmClob(v), stmt.bindParams[i], stmt.dmConn)
   750  			if err != nil {
   751  				return nil, err
   752  			}
   753  		case DmArray:
   754  			bindInParam(stmt, i, ARRAY, firstRow)
   755  			da := &v
   756  			da, err = da.create(stmt.dmConn)
   757  			if err != nil {
   758  				return nil, err
   759  			}
   760  
   761  			bytes[i], err = G2DB.fromArray(da, stmt.bindParams[i], stmt.dmConn)
   762  		case DmStruct:
   763  			bindInParam(stmt, i, CLASS, firstRow)
   764  			ds := &v
   765  			ds, err = ds.create(stmt.dmConn)
   766  			if err != nil {
   767  				return nil, err
   768  			}
   769  
   770  			bytes[i], err = G2DB.fromStruct(ds, stmt.bindParams[i], stmt.dmConn)
   771  		case sql.Out:
   772  			var cvt = converter{stmt.dmConn, false}
   773  			if arg, err = cvt.ConvertValue(v.Dest); err != nil {
   774  				return nil, err
   775  			}
   776  			goto nextSwitch
   777  
   778  		case *DmTimestamp:
   779  			bindInParam(stmt, i, DATETIME, firstRow)
   780  			bytes[i], err = G2DB.fromTime(v.ToTime(), stmt.bindParams[i], stmt.dmConn)
   781  		case *DmIntervalDT:
   782  			bindInParam(stmt, i, INTERVAL_DT, firstRow)
   783  			if stmt.bindParams[i].typeFlag != TYPE_FLAG_EXACT {
   784  				stmt.bindParams[i].scale = int32(v.scaleForSvr)
   785  			}
   786  			bytes[i], err = G2DB.fromDmIntervalDT(*v, stmt.bindParams[i], stmt.dmConn)
   787  		case *DmIntervalYM:
   788  			bindInParam(stmt, i, INTERVAL_YM, firstRow)
   789  			if stmt.bindParams[i].typeFlag != TYPE_FLAG_EXACT {
   790  				stmt.bindParams[i].scale = int32(v.scaleForSvr)
   791  			}
   792  			bytes[i], err = G2DB.fromDmdbIntervalYM(*v, stmt.bindParams[i], stmt.dmConn)
   793  		case *DmDecimal:
   794  			bindInParam(stmt, i, DECIMAL, firstRow)
   795  			bytes[i], err = G2DB.fromDecimal(*v, stmt.bindParams[i], stmt.dmConn)
   796  		case *DmBlob:
   797  			bindInParam(stmt, i, BLOB, firstRow)
   798  			bytes[i], err = G2DB.fromBlob(DmBlob(*v), stmt.bindParams[i], stmt.dmConn)
   799  		case *DmClob:
   800  			bindInParam(stmt, i, CLOB, firstRow)
   801  			bytes[i], err = G2DB.fromClob(DmClob(*v), stmt.bindParams[i], stmt.dmConn)
   802  		case *DmArray:
   803  			bindInParam(stmt, i, ARRAY, firstRow)
   804  			v, err = v.create(stmt.dmConn)
   805  			if err != nil {
   806  				return nil, err
   807  			}
   808  
   809  			bytes[i], err = G2DB.fromArray(v, stmt.bindParams[i], stmt.dmConn)
   810  		case *DmStruct:
   811  			bindInParam(stmt, i, CLASS, firstRow)
   812  			v, err = v.create(stmt.dmConn)
   813  			if err != nil {
   814  				return nil, err
   815  			}
   816  
   817  			bytes[i], err = G2DB.fromStruct(v, stmt.bindParams[i], stmt.dmConn)
   818  		case *driver.Rows:
   819  			if stmt.serverParams[i].colType == CURSOR {
   820  				bindInParam(stmt, i, CURSOR, firstRow)
   821  				if stmt.bindParams[i].cursorStmt == nil {
   822  					stmt.bindParams[i].cursorStmt = &DmStatement{dmConn: stmt.dmConn}
   823  					stmt.bindParams[i].cursorStmt.resetFilterable(&stmt.dmConn.filterable)
   824  					err = stmt.bindParams[i].cursorStmt.dmConn.Access.Dm_build_1403(stmt.bindParams[i].cursorStmt)
   825  				}
   826  			}
   827  		case io.Reader:
   828  			bindInParam(stmt, i, stmt.serverParams[i].colType, firstRow)
   829  			bytes[i], err = G2DB.fromReader(io.Reader(v), stmt.serverParams[i], stmt.dmConn)
   830  			if err != nil {
   831  				return nil, err
   832  			}
   833  		default:
   834  			err = ECGO_UNSUPPORTED_INPARAM_TYPE.throw()
   835  		}
   836  
   837  		if err != nil {
   838  			return nil, err
   839  		}
   840  
   841  	}
   842  	checkBindParameters(stmt, bytes)
   843  
   844  	return bytes, nil
   845  }
   846  
   847  type converter struct {
   848  	conn    *DmConnection
   849  	isBatch bool
   850  }
   851  type decimalDecompose interface {
   852  	Decompose(buf []byte) (form byte, negative bool, coefficient []byte, exponent int32)
   853  }
   854  
   855  func (c *converter) ConvertValue(v interface{}) (driver.Value, error) {
   856  	if driver.IsValue(v) {
   857  		return v, nil
   858  	}
   859  
   860  	switch vr := v.(type) {
   861  	case driver.Valuer:
   862  		sv, err := callValuerValue(vr)
   863  		if err != nil {
   864  			return nil, err
   865  		}
   866  
   867  		return sv, nil
   868  
   869  	case decimalDecompose, DmDecimal, *DmDecimal, DmTimestamp, *DmTimestamp, DmIntervalDT, *DmIntervalDT,
   870  		DmIntervalYM, *DmIntervalYM, driver.Rows, *driver.Rows, DmArray, *DmArray, DmStruct, *DmStruct, sql.Out:
   871  		return vr, nil
   872  	case big.Int:
   873  		return NewDecimalFromBigInt(&vr)
   874  	case big.Float:
   875  		return NewDecimalFromBigFloat(&vr)
   876  	case DmClob:
   877  
   878  		if vr.connection == nil {
   879  			vr.connection = c.conn
   880  		}
   881  		return vr, nil
   882  	case *DmClob:
   883  
   884  		if vr.connection == nil {
   885  			vr.connection = c.conn
   886  		}
   887  		return vr, nil
   888  	case DmBlob:
   889  
   890  		if vr.connection == nil {
   891  			vr.connection = c.conn
   892  		}
   893  		return vr, nil
   894  	case *DmBlob:
   895  
   896  		if vr.connection == nil {
   897  			vr.connection = c.conn
   898  		}
   899  		return vr, nil
   900  	case io.Reader:
   901  		return vr, nil
   902  	}
   903  
   904  	rv := reflect.ValueOf(v)
   905  	switch rv.Kind() {
   906  	case reflect.Ptr:
   907  		if rv.IsNil() {
   908  			return nil, nil
   909  		} else {
   910  			return c.ConvertValue(rv.Elem().Interface())
   911  		}
   912  	case reflect.Int:
   913  		return rv.Int(), nil
   914  	case reflect.Int8:
   915  		return int8(rv.Int()), nil
   916  	case reflect.Int16:
   917  		return int16(rv.Int()), nil
   918  	case reflect.Int32:
   919  		return int32(rv.Int()), nil
   920  	case reflect.Int64:
   921  		return int64(rv.Int()), nil
   922  	case reflect.Uint8:
   923  		return uint8(rv.Uint()), nil
   924  	case reflect.Uint16:
   925  		return uint16(rv.Uint()), nil
   926  	case reflect.Uint32:
   927  		return uint32(rv.Uint()), nil
   928  	case reflect.Uint64, reflect.Uint:
   929  		u64 := rv.Uint()
   930  		if u64 >= 1<<63 {
   931  			bigInt := &big.Int{}
   932  			bigInt.SetString(strconv.FormatUint(u64, 10), 10)
   933  			return NewDecimalFromBigInt(bigInt)
   934  		}
   935  		return int64(u64), nil
   936  	case reflect.Float32:
   937  		return float32(rv.Float()), nil
   938  	case reflect.Float64:
   939  		return float64(rv.Float()), nil
   940  	case reflect.Bool:
   941  		return rv.Bool(), nil
   942  	case reflect.Slice:
   943  		ek := rv.Type().Elem().Kind()
   944  		if ek == reflect.Uint8 {
   945  			return rv.Bytes(), nil
   946  		} else if ek == reflect.Slice {
   947  			c.isBatch = true
   948  			return v, nil
   949  		}
   950  		return nil, fmt.Errorf("unsupported type %T, a slice of %s", v, ek)
   951  	case reflect.String:
   952  		return rv.String(), nil
   953  	}
   954  	return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
   955  }
   956  
   957  var valuerReflectType = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
   958  
   959  func callValuerValue(vr driver.Valuer) (v driver.Value, err error) {
   960  	if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Ptr &&
   961  		rv.IsNil() &&
   962  		rv.Type().Elem().Implements(valuerReflectType) {
   963  		return nil, nil
   964  	}
   965  	return vr.Value()
   966  }
   967  
   968  func namedValueToValue(stmt *DmStatement, named []driver.NamedValue) ([]driver.Value, error) {
   969  
   970  	dargs := make([]driver.Value, stmt.paramCount)
   971  	for i, _ := range dargs {
   972  		found := false
   973  		for _, nv := range named {
   974  			if nv.Name != "" && strings.ToUpper(nv.Name) == strings.ToUpper(stmt.serverParams[i].name) {
   975  				dargs[i] = nv.Value
   976  				found = true
   977  				break
   978  			}
   979  		}
   980  
   981  		if !found && i < len(named) {
   982  			dargs[i] = named[i].Value
   983  		}
   984  
   985  	}
   986  	return dargs, nil
   987  }
   988  
   989  func (stmt *DmStatement) executeInner(args []driver.Value, executeType int16) (err error) {
   990  
   991  	var bytes []interface{}
   992  
   993  	if stmt.paramCount > 0 {
   994  		bytes, err = encodeArgs(stmt, args, true)
   995  		if err != nil {
   996  			return err
   997  		}
   998  	}
   999  	stmt.execInfo, err = stmt.dmConn.Access.Dm_build_1453(stmt, bytes, false)
  1000  	if err != nil {
  1001  		return err
  1002  	}
  1003  	if stmt.execInfo.outParamDatas != nil {
  1004  		for i, outParamData := range stmt.execInfo.outParamDatas {
  1005  			if stmt.bindParams[i].ioType == IO_TYPE_IN || stmt.bindParams[i].ioType == IO_TYPE_UNKNOWN {
  1006  				continue
  1007  			}
  1008  
  1009  			var v sql.Out
  1010  			ok := true
  1011  			for ok {
  1012  				if v, ok = args[i].(sql.Out); ok {
  1013  					args[i] = v.Dest
  1014  				}
  1015  			}
  1016  
  1017  			if sc, ok := args[i].(sql.Scanner); ok {
  1018  				var v interface{}
  1019  				if outParamData == nil && stmt.bindParams[i].colType != CURSOR {
  1020  					v = nil
  1021  					if err = sc.Scan(v); err != nil {
  1022  						return err
  1023  					}
  1024  					continue
  1025  				}
  1026  
  1027  				switch stmt.bindParams[i].colType {
  1028  				case BOOLEAN:
  1029  					v, err = DB2G.toBool(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1030  				case BIT:
  1031  					if strings.ToLower(stmt.bindParams[i].typeName) == "boolean" {
  1032  						v, err = DB2G.toBool(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1033  					}
  1034  
  1035  					v, err = DB2G.toInt8(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1036  				case TINYINT:
  1037  					v, err = DB2G.toInt8(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1038  				case SMALLINT:
  1039  					v, err = DB2G.toInt16(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1040  				case INT:
  1041  					v, err = DB2G.toInt32(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1042  				case BIGINT:
  1043  					v, err = DB2G.toInt64(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1044  				case REAL:
  1045  					v, err = DB2G.toFloat32(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1046  				case DOUBLE:
  1047  					v, err = DB2G.toFloat64(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1048  				case DATE, TIME, DATETIME, TIME_TZ, DATETIME_TZ, DATETIME2, DATETIME2_TZ:
  1049  					v, err = DB2G.toTime(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1050  				case INTERVAL_DT:
  1051  					v = newDmIntervalDTByBytes(outParamData)
  1052  				case INTERVAL_YM:
  1053  					v = newDmIntervalYMByBytes(outParamData)
  1054  				case DECIMAL:
  1055  					v, err = DB2G.toDmDecimal(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1056  				case BINARY, VARBINARY:
  1057  					v = util.StringUtil.BytesToHexString(outParamData, false)
  1058  				case BLOB:
  1059  					v = DB2G.toDmBlob(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1060  				case CHAR, VARCHAR2, VARCHAR:
  1061  					v = DB2G.toString(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1062  				case CLOB:
  1063  					v = DB2G.toDmClob(outParamData, stmt.dmConn, &stmt.bindParams[i].column)
  1064  				case ARRAY:
  1065  					v, err = TypeDataSV.bytesToArray(outParamData, nil, stmt.bindParams[i].typeDescriptor)
  1066  				case CLASS:
  1067  					v, err = TypeDataSV.bytesToObj(outParamData, nil, stmt.bindParams[i].typeDescriptor)
  1068  				case CURSOR:
  1069  					var tmpExecInfo *execRetInfo
  1070  					if tmpExecInfo, err = stmt.dmConn.Access.Dm_build_1463(stmt.bindParams[i].cursorStmt, 1); err != nil {
  1071  						return err
  1072  					}
  1073  					if tmpExecInfo.hasResultSet {
  1074  						v = newDmRows(newInnerRows(0, stmt.bindParams[i].cursorStmt, tmpExecInfo))
  1075  					}
  1076  				default:
  1077  					err = ECGO_UNSUPPORTED_OUTPARAM_TYPE.throw()
  1078  				}
  1079  				if err == nil {
  1080  					err = sc.Scan(v)
  1081  				}
  1082  			} else if args[i] == nil {
  1083  				if outParamData == nil && stmt.bindParams[i].colType != CURSOR {
  1084  					continue
  1085  				}
  1086  
  1087  				switch stmt.bindParams[i].colType {
  1088  				case BOOLEAN:
  1089  					args[i], err = DB2G.toBool(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1090  				case BIT:
  1091  					if strings.ToLower(stmt.bindParams[i].typeName) == "boolean" {
  1092  						args[i], err = DB2G.toBool(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1093  					}
  1094  
  1095  					args[i], err = DB2G.toInt8(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1096  				case TINYINT:
  1097  					args[i], err = DB2G.toInt8(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1098  				case SMALLINT:
  1099  					args[i], err = DB2G.toInt16(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1100  				case INT:
  1101  					args[i], err = DB2G.toInt32(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1102  				case BIGINT:
  1103  					args[i], err = DB2G.toInt64(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1104  				case REAL:
  1105  					args[i], err = DB2G.toFloat32(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1106  				case DOUBLE:
  1107  					args[i], err = DB2G.toFloat64(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1108  				case DATE, TIME, DATETIME, TIME_TZ, DATETIME_TZ, DATETIME2, DATETIME2_TZ:
  1109  					args[i], err = DB2G.toTime(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1110  				case INTERVAL_DT:
  1111  					args[i] = newDmIntervalDTByBytes(outParamData)
  1112  				case INTERVAL_YM:
  1113  					args[i] = newDmIntervalYMByBytes(outParamData)
  1114  				case DECIMAL:
  1115  					args[i], err = DB2G.toDmDecimal(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1116  				case BINARY, VARBINARY:
  1117  					args[i] = util.StringUtil.BytesToHexString(outParamData, false)
  1118  				case BLOB:
  1119  					args[i] = DB2G.toDmBlob(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1120  				case CHAR, VARCHAR2, VARCHAR:
  1121  					args[i] = DB2G.toString(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1122  				case CLOB:
  1123  					args[i] = DB2G.toDmClob(outParamData, stmt.dmConn, &stmt.bindParams[i].column)
  1124  				default:
  1125  					err = ECGO_UNSUPPORTED_OUTPARAM_TYPE.throw()
  1126  				}
  1127  			} else {
  1128  				switch v := args[i].(type) {
  1129  				case *string:
  1130  					if outParamData == nil {
  1131  						*v = ""
  1132  					} else {
  1133  						*v = DB2G.toString(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1134  					}
  1135  				case *sql.NullString:
  1136  					if outParamData == nil {
  1137  						v.String = ""
  1138  						v.Valid = false
  1139  					} else {
  1140  						v.String = DB2G.toString(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1141  						v.Valid = true
  1142  					}
  1143  				case *[]byte:
  1144  					if outParamData == nil {
  1145  						*v = nil
  1146  					} else {
  1147  						var val []byte
  1148  						if val, err = DB2G.toBytes(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
  1149  							return err
  1150  						}
  1151  						*v = val
  1152  					}
  1153  				case *bool:
  1154  					if outParamData == nil {
  1155  						*v = false
  1156  					} else {
  1157  						var val bool
  1158  						if val, err = DB2G.toBool(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
  1159  							return err
  1160  						}
  1161  						*v = val
  1162  					}
  1163  				case *sql.NullBool:
  1164  					if outParamData == nil {
  1165  						v.Bool = false
  1166  						v.Valid = false
  1167  					} else {
  1168  						var val bool
  1169  						if val, err = DB2G.toBool(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
  1170  							return err
  1171  						}
  1172  						v.Bool = val
  1173  						v.Valid = true
  1174  					}
  1175  				case *int8:
  1176  					if outParamData == nil {
  1177  						*v = 0
  1178  					} else {
  1179  						var val int8
  1180  						if val, err = DB2G.toInt8(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
  1181  							return err
  1182  						}
  1183  						*v = val
  1184  					}
  1185  				case *int16:
  1186  					if outParamData == nil {
  1187  						*v = 0
  1188  					} else {
  1189  						var val int16
  1190  						if val, err = DB2G.toInt16(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
  1191  							return err
  1192  						}
  1193  						*v = val
  1194  					}
  1195  				case *int32:
  1196  					if outParamData == nil {
  1197  						*v = 0
  1198  					} else {
  1199  						var val int32
  1200  						if val, err = DB2G.toInt32(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
  1201  							return err
  1202  						}
  1203  						*v = val
  1204  					}
  1205  				case *sql.NullInt32:
  1206  					if outParamData == nil {
  1207  						v.Int32 = 0
  1208  						v.Valid = false
  1209  					} else {
  1210  						var val int32
  1211  						if val, err = DB2G.toInt32(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
  1212  							return err
  1213  						}
  1214  						v.Int32 = val
  1215  						v.Valid = true
  1216  					}
  1217  				case *int64:
  1218  					if outParamData == nil {
  1219  						*v = 0
  1220  					} else {
  1221  						var val int64
  1222  						if val, err = DB2G.toInt64(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
  1223  							return err
  1224  						}
  1225  						*v = val
  1226  					}
  1227  				case *sql.NullInt64:
  1228  					if outParamData == nil {
  1229  						v.Int64 = 0
  1230  						v.Valid = false
  1231  					} else {
  1232  						var val int64
  1233  						if val, err = DB2G.toInt64(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
  1234  							return err
  1235  						}
  1236  						v.Int64 = val
  1237  						v.Valid = true
  1238  					}
  1239  				case *uint8:
  1240  					if outParamData == nil {
  1241  						*v = 0
  1242  					} else {
  1243  						var val uint8
  1244  						if val, err = DB2G.toByte(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
  1245  							return err
  1246  						}
  1247  						*v = val
  1248  					}
  1249  				case *uint16:
  1250  					if outParamData == nil {
  1251  						*v = 0
  1252  					} else {
  1253  						var val uint16
  1254  						if val, err = DB2G.toUInt16(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
  1255  							return err
  1256  						}
  1257  						*v = val
  1258  					}
  1259  				case *uint32:
  1260  					if outParamData == nil {
  1261  						*v = 0
  1262  					} else {
  1263  						var val uint32
  1264  						if val, err = DB2G.toUInt32(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
  1265  							return err
  1266  						}
  1267  						*v = val
  1268  					}
  1269  				case *uint64:
  1270  					if outParamData == nil {
  1271  						*v = 0
  1272  					} else {
  1273  						var val uint64
  1274  						if val, err = DB2G.toUInt64(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
  1275  							return err
  1276  						}
  1277  						*v = val
  1278  					}
  1279  				case *int:
  1280  					if outParamData == nil {
  1281  						*v = 0
  1282  					} else {
  1283  						var val int
  1284  						if val, err = DB2G.toInt(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
  1285  							return err
  1286  						}
  1287  						*v = val
  1288  					}
  1289  				case *uint:
  1290  					if outParamData == nil {
  1291  						*v = 0
  1292  					} else {
  1293  						var val uint
  1294  						if val, err = DB2G.toUInt(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
  1295  							return err
  1296  						}
  1297  						*v = val
  1298  					}
  1299  				case *float32:
  1300  					if outParamData == nil {
  1301  						*v = 0.0
  1302  					} else {
  1303  						var val float32
  1304  						if val, err = DB2G.toFloat32(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
  1305  							return err
  1306  						}
  1307  						*v = val
  1308  					}
  1309  				case *float64:
  1310  					if outParamData == nil {
  1311  						*v = 0.0
  1312  					} else {
  1313  						var val float64
  1314  						if val, err = DB2G.toFloat64(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
  1315  							return err
  1316  						}
  1317  						*v = val
  1318  					}
  1319  				case *sql.NullFloat64:
  1320  					if outParamData == nil {
  1321  						v.Float64 = 0.0
  1322  						v.Valid = false
  1323  					} else {
  1324  						var val float64
  1325  						if val, err = DB2G.toFloat64(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
  1326  							return err
  1327  						}
  1328  						v.Float64 = val
  1329  						v.Valid = true
  1330  					}
  1331  				case *time.Time:
  1332  					if outParamData == nil {
  1333  						*v = time.Time{}
  1334  					} else {
  1335  						var val time.Time
  1336  						if val, err = DB2G.toTime(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
  1337  							return err
  1338  						}
  1339  						*v = val
  1340  					}
  1341  				case *sql.NullTime:
  1342  					if outParamData == nil {
  1343  						v.Time = time.Time{}
  1344  						v.Valid = false
  1345  					} else {
  1346  						var val time.Time
  1347  						if val, err = DB2G.toTime(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
  1348  							return err
  1349  						}
  1350  						v.Time = val
  1351  						v.Valid = true
  1352  					}
  1353  				case *DmTimestamp:
  1354  					if outParamData == nil {
  1355  						*v = DmTimestamp{}
  1356  					} else {
  1357  						*v = *newDmTimestampFromBytes(outParamData, stmt.bindParams[i].column, stmt.dmConn)
  1358  					}
  1359  				case *DmIntervalDT:
  1360  					if outParamData == nil {
  1361  						*v = DmIntervalDT{}
  1362  					} else {
  1363  						*v = *newDmIntervalDTByBytes(outParamData)
  1364  					}
  1365  				case *DmIntervalYM:
  1366  					if outParamData == nil {
  1367  						*v = DmIntervalYM{}
  1368  					} else {
  1369  						*v = *newDmIntervalYMByBytes(outParamData)
  1370  					}
  1371  				case *DmDecimal:
  1372  					if outParamData == nil {
  1373  						*v = DmDecimal{}
  1374  					} else {
  1375  						var val *DmDecimal
  1376  						if val, err = DB2G.toDmDecimal(outParamData, &stmt.bindParams[i].column, stmt.dmConn); err != nil {
  1377  							return err
  1378  						}
  1379  						*v = *val
  1380  					}
  1381  				case *DmBlob:
  1382  					if outParamData == nil {
  1383  						*v = DmBlob{}
  1384  					} else {
  1385  						*v = *DB2G.toDmBlob(outParamData, &stmt.bindParams[i].column, stmt.dmConn)
  1386  					}
  1387  				case *DmClob:
  1388  					if outParamData == nil {
  1389  						*v = DmClob{}
  1390  					} else {
  1391  						*v = *DB2G.toDmClob(outParamData, stmt.dmConn, &stmt.bindParams[i].column)
  1392  					}
  1393  				case *driver.Rows:
  1394  					if stmt.bindParams[i].colType == CURSOR {
  1395  						var tmpExecInfo *execRetInfo
  1396  						tmpExecInfo, err = stmt.dmConn.Access.Dm_build_1463(stmt.bindParams[i].cursorStmt, 1)
  1397  						if err != nil {
  1398  							return err
  1399  						}
  1400  
  1401  						if tmpExecInfo.hasResultSet {
  1402  							*v = newDmRows(newInnerRows(0, stmt.bindParams[i].cursorStmt, tmpExecInfo))
  1403  						} else {
  1404  							*v = nil
  1405  						}
  1406  					}
  1407  				case *DmArray:
  1408  					if outParamData == nil {
  1409  						*v = DmArray{}
  1410  					} else {
  1411  						var val *DmArray
  1412  						if val, err = TypeDataSV.bytesToArray(outParamData, nil, stmt.bindParams[i].typeDescriptor); err != nil {
  1413  							return err
  1414  						}
  1415  						*v = *val
  1416  					}
  1417  				case *DmStruct:
  1418  					if outParamData == nil {
  1419  						*v = DmStruct{}
  1420  					} else {
  1421  						var tmp interface{}
  1422  						if tmp, err = TypeDataSV.bytesToObj(outParamData, nil, stmt.bindParams[i].typeDescriptor); err != nil {
  1423  							return err
  1424  						}
  1425  						if val, ok := tmp.(*DmStruct); ok {
  1426  							*v = *val
  1427  						}
  1428  					}
  1429  				default:
  1430  					err = ECGO_UNSUPPORTED_OUTPARAM_TYPE.throw()
  1431  				}
  1432  			}
  1433  			if err != nil {
  1434  				return err
  1435  			}
  1436  		}
  1437  
  1438  	}
  1439  	return err
  1440  }
  1441  
  1442  func (stmt *DmStatement) executeBatch(args []driver.Value) (err error) {
  1443  
  1444  	var bytes [][]interface{}
  1445  
  1446  	if stmt.execInfo.retSqlType == Dm_build_110 || stmt.execInfo.retSqlType == Dm_build_115 {
  1447  		return ECGO_INVALID_SQL_TYPE.throw()
  1448  	}
  1449  
  1450  	if stmt.paramCount > 0 && args != nil && len(args) > 0 {
  1451  
  1452  		if len(args) == 1 || stmt.dmConn.dmConnector.batchType == 2 ||
  1453  			(stmt.dmConn.dmConnector.batchNotOnCall && stmt.execInfo.retSqlType == Dm_build_111) {
  1454  			return stmt.executeBatchByRow(args)
  1455  		} else {
  1456  			for i, arg := range args {
  1457  				var newArg []driver.Value
  1458  				for _, a := range arg.([]interface{}) {
  1459  					newArg = append(newArg, a)
  1460  				}
  1461  				tmpBytes, err := encodeArgs(stmt, newArg, i == 0)
  1462  				if err != nil {
  1463  					return err
  1464  				}
  1465  				bytes = append(bytes, tmpBytes)
  1466  			}
  1467  			stmt.execInfo, err = stmt.dmConn.Access.Dm_build_1442(stmt, bytes, stmt.preExec)
  1468  		}
  1469  	}
  1470  	return err
  1471  }
  1472  
  1473  func (stmt *DmStatement) executeBatchByRow(args []driver.Value) (err error) {
  1474  	count := len(args)
  1475  	stmt.execInfo = NewExceInfo()
  1476  	stmt.execInfo.updateCounts = make([]int64, count)
  1477  	var sqlErrBuilder strings.Builder
  1478  	for i := 0; i < count; i++ {
  1479  		tmpExecInfo, err := stmt.dmConn.Access.Dm_build_1453(stmt, args[i].([]interface{}), stmt.preExec || i != 0)
  1480  		if err == nil {
  1481  			stmt.execInfo.union(tmpExecInfo, i, 1)
  1482  		} else {
  1483  			stmt.execInfo.updateCounts[i] = -1
  1484  			if stmt.dmConn.dmConnector.continueBatchOnError {
  1485  				sqlErrBuilder.WriteString("row[" + strconv.Itoa(i) + "]:" + err.Error() + util.LINE_SEPARATOR)
  1486  			} else {
  1487  				return ECGO_BATCH_ERROR.addDetailln(err.Error()).throw()
  1488  			}
  1489  		}
  1490  	}
  1491  	if sqlErrBuilder.Len() > 0 {
  1492  		return EC_BP_WITH_ERROR.addDetail(sqlErrBuilder.String()).throw()
  1493  	}
  1494  	return nil
  1495  }