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