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

     1  /*
     2   * Copyright (c) 2000-2018, 达梦数据库有限公司.
     3   * All rights reserved.
     4   */
     5  package dm
     6  
     7  import (
     8  	"bytes"
     9  	"context"
    10  	"database/sql"
    11  	"database/sql/driver"
    12  	"fmt"
    13  	"sync"
    14  	"sync/atomic"
    15  
    16  	"gitee.com/chunanyong/dm/parser"
    17  
    18  	"gitee.com/chunanyong/dm/util"
    19  	"golang.org/x/text/encoding"
    20  )
    21  
    22  type DmConnection struct {
    23  	filterable
    24  	mu sync.Mutex
    25  
    26  	dmConnector *DmConnector
    27  	Access      *dm_build_1345
    28  	stmtMap     map[int32]*DmStatement
    29  
    30  	lastExecInfo       *execRetInfo
    31  	lexer              *parser.Lexer
    32  	encode             encoding.Encoding
    33  	encodeBuffer       *bytes.Buffer
    34  	transformReaderDst []byte
    35  	transformReaderSrc []byte
    36  
    37  	serverEncoding     string
    38  	GlobalServerSeries int
    39  	ServerVersion      string
    40  	Malini2            bool
    41  	Execute2           bool
    42  	LobEmptyCompOrcl   bool
    43  	IsoLevel           int32
    44  	ReadOnly           bool
    45  	NewLobFlag         bool
    46  	sslEncrypt         int
    47  	MaxRowSize         int32
    48  	DDLAutoCommit      bool
    49  	BackslashEscape    bool
    50  	SvrStat            int32
    51  	SvrMode            int32
    52  	ConstParaOpt       bool
    53  	DbTimezone         int16
    54  	LifeTimeRemainder  int16
    55  	InstanceName       string
    56  	Schema             string
    57  	LastLoginIP        string
    58  	LastLoginTime      string
    59  	FailedAttempts     int32
    60  	LoginWarningID     int32
    61  	GraceTimeRemainder int32
    62  	Guid               string
    63  	DbName             string
    64  	StandbyHost        string
    65  	StandbyPort        int32
    66  	StandbyCount       int32
    67  	SessionID          int64
    68  	OracleDateLanguage byte
    69  	FormatDate         string
    70  	FormatTimestamp    string
    71  	FormatTimestampTZ  string
    72  	FormatTime         string
    73  	FormatTimeTZ       string
    74  	Local              bool
    75  	MsgVersion         int32
    76  	TrxStatus          int32
    77  	dscControl         bool
    78  	trxFinish          bool
    79  	autoCommit         bool
    80  	isBatch            bool
    81  
    82  	watching bool
    83  	watcher  chan<- context.Context
    84  	closech  chan struct{}
    85  	finished chan<- struct{}
    86  	canceled atomicError
    87  	closed   atomicBool
    88  }
    89  
    90  func (conn *DmConnection) setTrxFinish(status int32) {
    91  	switch status & Dm_build_132 {
    92  	case Dm_build_129, Dm_build_130, Dm_build_131:
    93  		conn.trxFinish = true
    94  	default:
    95  		conn.trxFinish = false
    96  	}
    97  }
    98  
    99  func (dmConn *DmConnection) init() {
   100  
   101  	dmConn.stmtMap = make(map[int32]*DmStatement)
   102  	dmConn.DbTimezone = 0
   103  	dmConn.GlobalServerSeries = 0
   104  	dmConn.MaxRowSize = 0
   105  	dmConn.LobEmptyCompOrcl = false
   106  	dmConn.ReadOnly = false
   107  	dmConn.DDLAutoCommit = false
   108  	dmConn.ConstParaOpt = false
   109  	dmConn.IsoLevel = -1
   110  	dmConn.Malini2 = true
   111  	dmConn.NewLobFlag = true
   112  	dmConn.Execute2 = true
   113  	dmConn.serverEncoding = ENCODING_GB18030
   114  	dmConn.TrxStatus = Dm_build_80
   115  	dmConn.setTrxFinish(dmConn.TrxStatus)
   116  	dmConn.OracleDateLanguage = byte(Locale)
   117  	dmConn.lastExecInfo = NewExceInfo()
   118  	dmConn.MsgVersion = Dm_build_13
   119  
   120  	dmConn.idGenerator = dmConnIDGenerator
   121  }
   122  
   123  func (dmConn *DmConnection) reset() {
   124  	dmConn.DbTimezone = 0
   125  	dmConn.GlobalServerSeries = 0
   126  	dmConn.MaxRowSize = 0
   127  	dmConn.LobEmptyCompOrcl = false
   128  	dmConn.ReadOnly = false
   129  	dmConn.DDLAutoCommit = false
   130  	dmConn.ConstParaOpt = false
   131  	dmConn.IsoLevel = -1
   132  	dmConn.Malini2 = true
   133  	dmConn.NewLobFlag = true
   134  	dmConn.Execute2 = true
   135  	dmConn.serverEncoding = ENCODING_GB18030
   136  	dmConn.TrxStatus = Dm_build_80
   137  	dmConn.setTrxFinish(dmConn.TrxStatus)
   138  }
   139  
   140  func (dc *DmConnection) checkClosed() error {
   141  	if dc.closed.IsSet() {
   142  		return driver.ErrBadConn
   143  	}
   144  
   145  	return nil
   146  }
   147  
   148  func (dc *DmConnection) executeInner(query string, execType int16) (interface{}, error) {
   149  
   150  	stmt, err := NewDmStmt(dc, query)
   151  
   152  	if err != nil {
   153  		return nil, err
   154  	}
   155  
   156  	if execType == Dm_build_97 {
   157  		defer stmt.close()
   158  	}
   159  
   160  	stmt.innerUsed = true
   161  	if stmt.dmConn.dmConnector.escapeProcess {
   162  		stmt.nativeSql, err = stmt.dmConn.escape(stmt.nativeSql, stmt.dmConn.dmConnector.keyWords)
   163  		if err != nil {
   164  			stmt.close()
   165  			return nil, err
   166  		}
   167  	}
   168  
   169  	var optParamList []OptParameter
   170  
   171  	if stmt.dmConn.ConstParaOpt {
   172  		optParamList = make([]OptParameter, 0)
   173  		stmt.nativeSql, optParamList, err = stmt.dmConn.execOpt(stmt.nativeSql, optParamList, stmt.dmConn.getServerEncoding())
   174  		if err != nil {
   175  			stmt.close()
   176  			optParamList = nil
   177  		}
   178  	}
   179  
   180  	if execType == Dm_build_96 && dc.dmConnector.enRsCache {
   181  		rpv, err := rp.get(stmt, query)
   182  		if err != nil {
   183  			return nil, err
   184  		}
   185  
   186  		if rpv != nil {
   187  			stmt.execInfo = rpv.execInfo
   188  			dc.lastExecInfo = rpv.execInfo
   189  			return newDmRows(rpv.getResultSet(stmt)), nil
   190  		}
   191  	}
   192  
   193  	var info *execRetInfo
   194  
   195  	if optParamList != nil && len(optParamList) > 0 {
   196  		info, err = dc.Access.Dm_build_1425(stmt, optParamList)
   197  		if err != nil {
   198  			stmt.nativeSql = query
   199  			info, err = dc.Access.Dm_build_1431(stmt, execType)
   200  		}
   201  	} else {
   202  		info, err = dc.Access.Dm_build_1431(stmt, execType)
   203  	}
   204  
   205  	if err != nil {
   206  		stmt.close()
   207  		return nil, err
   208  	}
   209  	dc.lastExecInfo = info
   210  
   211  	if execType == Dm_build_96 && info.hasResultSet {
   212  		return newDmRows(newInnerRows(0, stmt, info)), nil
   213  	} else {
   214  		return newDmResult(stmt, info), nil
   215  	}
   216  }
   217  
   218  func g2dbIsoLevel(isoLevel int32) int32 {
   219  	switch isoLevel {
   220  	case 1:
   221  		return Dm_build_84
   222  	case 2:
   223  		return Dm_build_85
   224  	case 4:
   225  		return Dm_build_86
   226  	case 6:
   227  		return Dm_build_87
   228  	default:
   229  		return -1
   230  	}
   231  }
   232  
   233  func (dc *DmConnection) Begin() (driver.Tx, error) {
   234  	if len(dc.filterChain.filters) == 0 {
   235  		return dc.begin()
   236  	} else {
   237  		return dc.filterChain.reset().DmConnectionBegin(dc)
   238  	}
   239  }
   240  
   241  func (dc *DmConnection) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
   242  	if len(dc.filterChain.filters) == 0 {
   243  		return dc.beginTx(ctx, opts)
   244  	}
   245  	return dc.filterChain.reset().DmConnectionBeginTx(dc, ctx, opts)
   246  }
   247  
   248  func (dc *DmConnection) Commit() error {
   249  	if len(dc.filterChain.filters) == 0 {
   250  		return dc.commit()
   251  	} else {
   252  		return dc.filterChain.reset().DmConnectionCommit(dc)
   253  	}
   254  }
   255  
   256  func (dc *DmConnection) Rollback() error {
   257  	if len(dc.filterChain.filters) == 0 {
   258  		return dc.rollback()
   259  	} else {
   260  		return dc.filterChain.reset().DmConnectionRollback(dc)
   261  	}
   262  }
   263  
   264  func (dc *DmConnection) Close() error {
   265  	if len(dc.filterChain.filters) == 0 {
   266  		return dc.close()
   267  	} else {
   268  		return dc.filterChain.reset().DmConnectionClose(dc)
   269  	}
   270  }
   271  
   272  func (dc *DmConnection) Ping(ctx context.Context) error {
   273  	if len(dc.filterChain.filters) == 0 {
   274  		return dc.ping(ctx)
   275  	} else {
   276  		return dc.filterChain.reset().DmConnectionPing(dc, ctx)
   277  	}
   278  }
   279  
   280  func (dc *DmConnection) Exec(query string, args []driver.Value) (driver.Result, error) {
   281  	if len(dc.filterChain.filters) == 0 {
   282  		return dc.exec(query, args)
   283  	}
   284  	return dc.filterChain.reset().DmConnectionExec(dc, query, args)
   285  }
   286  
   287  func (dc *DmConnection) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
   288  	if len(dc.filterChain.filters) == 0 {
   289  		return dc.execContext(ctx, query, args)
   290  	}
   291  	return dc.filterChain.reset().DmConnectionExecContext(dc, ctx, query, args)
   292  }
   293  
   294  func (dc *DmConnection) Query(query string, args []driver.Value) (driver.Rows, error) {
   295  	if len(dc.filterChain.filters) == 0 {
   296  		return dc.query(query, args)
   297  	}
   298  	return dc.filterChain.reset().DmConnectionQuery(dc, query, args)
   299  }
   300  
   301  func (dc *DmConnection) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {
   302  	if len(dc.filterChain.filters) == 0 {
   303  		return dc.queryContext(ctx, query, args)
   304  	}
   305  	return dc.filterChain.reset().DmConnectionQueryContext(dc, ctx, query, args)
   306  }
   307  
   308  func (dc *DmConnection) Prepare(query string) (driver.Stmt, error) {
   309  	if len(dc.filterChain.filters) == 0 {
   310  		return dc.prepare(query)
   311  	}
   312  	return dc.filterChain.reset().DmConnectionPrepare(dc, query)
   313  }
   314  
   315  func (dc *DmConnection) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) {
   316  	if len(dc.filterChain.filters) == 0 {
   317  		return dc.prepareContext(ctx, query)
   318  	}
   319  	return dc.filterChain.reset().DmConnectionPrepareContext(dc, ctx, query)
   320  }
   321  
   322  func (dc *DmConnection) ResetSession(ctx context.Context) error {
   323  	if len(dc.filterChain.filters) == 0 {
   324  		return dc.resetSession(ctx)
   325  	}
   326  	if err := dc.filterChain.reset().DmConnectionResetSession(dc, ctx); err != nil {
   327  		return driver.ErrBadConn
   328  	} else {
   329  		return nil
   330  	}
   331  }
   332  
   333  func (dc *DmConnection) CheckNamedValue(nv *driver.NamedValue) error {
   334  	if len(dc.filterChain.filters) == 0 {
   335  		return dc.checkNamedValue(nv)
   336  	}
   337  	return dc.filterChain.reset().DmConnectionCheckNamedValue(dc, nv)
   338  }
   339  
   340  func (dc *DmConnection) begin() (*DmConnection, error) {
   341  	return dc.beginTx(context.Background(), driver.TxOptions{driver.IsolationLevel(sql.LevelDefault), false})
   342  }
   343  
   344  func (dc *DmConnection) beginTx(ctx context.Context, opts driver.TxOptions) (*DmConnection, error) {
   345  	if err := dc.watchCancel(ctx); err != nil {
   346  		return nil, err
   347  	}
   348  	defer dc.finish()
   349  
   350  	err := dc.checkClosed()
   351  	if err != nil {
   352  		return nil, err
   353  	}
   354  
   355  	dc.autoCommit = false
   356  
   357  	if sql.IsolationLevel(opts.Isolation) == sql.LevelDefault {
   358  		opts.Isolation = driver.IsolationLevel(sql.LevelReadCommitted)
   359  	}
   360  
   361  	if dc.ReadOnly != opts.ReadOnly {
   362  		dc.ReadOnly = opts.ReadOnly
   363  		var readonly = 0
   364  		if opts.ReadOnly {
   365  			readonly = 1
   366  		}
   367  		dc.exec(fmt.Sprintf("SP_SET_SESSION_READONLY(%d)", readonly), nil)
   368  	}
   369  
   370  	if dc.IsoLevel != int32(opts.Isolation) {
   371  		switch sql.IsolationLevel(opts.Isolation) {
   372  		case sql.LevelDefault, sql.LevelReadUncommitted:
   373  			return dc, nil
   374  		case sql.LevelReadCommitted, sql.LevelSerializable:
   375  			dc.IsoLevel = int32(opts.Isolation)
   376  		case sql.LevelRepeatableRead:
   377  			if dc.CompatibleMysql() {
   378  				dc.IsoLevel = int32(sql.LevelReadCommitted)
   379  			} else {
   380  				return nil, ECGO_INVALID_TRAN_ISOLATION.throw()
   381  			}
   382  		default:
   383  			return nil, ECGO_INVALID_TRAN_ISOLATION.throw()
   384  		}
   385  
   386  		err = dc.Access.Dm_build_1485(dc)
   387  		if err != nil {
   388  			return nil, err
   389  		}
   390  	}
   391  
   392  	return dc, nil
   393  }
   394  
   395  func (dc *DmConnection) commit() error {
   396  	err := dc.checkClosed()
   397  	if err != nil {
   398  		return err
   399  	}
   400  
   401  	defer func() {
   402  		dc.autoCommit = dc.dmConnector.autoCommit
   403  		if dc.ReadOnly {
   404  			dc.exec("SP_SET_SESSION_READONLY(0)", nil)
   405  		}
   406  	}()
   407  
   408  	if !dc.autoCommit {
   409  		err = dc.Access.Commit()
   410  		if err != nil {
   411  			return err
   412  		}
   413  		dc.trxFinish = true
   414  		return nil
   415  	} else if !dc.dmConnector.alwayseAllowCommit {
   416  		return ECGO_COMMIT_IN_AUTOCOMMIT_MODE.throw()
   417  	}
   418  
   419  	return nil
   420  }
   421  
   422  func (dc *DmConnection) rollback() error {
   423  	err := dc.checkClosed()
   424  	if err != nil {
   425  		return err
   426  	}
   427  
   428  	defer func() {
   429  		dc.autoCommit = dc.dmConnector.autoCommit
   430  		if dc.ReadOnly {
   431  			dc.exec("SP_SET_SESSION_READONLY(0)", nil)
   432  		}
   433  	}()
   434  
   435  	if !dc.autoCommit {
   436  		err = dc.Access.Rollback()
   437  		if err != nil {
   438  			return err
   439  		}
   440  		dc.trxFinish = true
   441  		return nil
   442  	} else if !dc.dmConnector.alwayseAllowCommit {
   443  		return ECGO_ROLLBACK_IN_AUTOCOMMIT_MODE.throw()
   444  	}
   445  
   446  	return nil
   447  }
   448  
   449  func (dc *DmConnection) reconnect() error {
   450  	err := dc.Access.Close()
   451  	if err != nil {
   452  		return err
   453  	}
   454  
   455  	for _, stmt := range dc.stmtMap {
   456  
   457  		for id, rs := range stmt.rsMap {
   458  			rs.Close()
   459  			delete(stmt.rsMap, id)
   460  		}
   461  	}
   462  
   463  	var newConn *DmConnection
   464  	if dc.dmConnector.group != nil {
   465  		if newConn, err = dc.dmConnector.group.connect(dc.dmConnector); err != nil {
   466  			return err
   467  		}
   468  	} else {
   469  		newConn, err = dc.dmConnector.connect(context.Background())
   470  	}
   471  
   472  	oldMap := dc.stmtMap
   473  	newConn.mu = dc.mu
   474  	newConn.filterable = dc.filterable
   475  	*dc = *newConn
   476  
   477  	for _, stmt := range oldMap {
   478  		if stmt.closed {
   479  			continue
   480  		}
   481  		err = dc.Access.Dm_build_1403(stmt)
   482  		if err != nil {
   483  			stmt.free()
   484  			continue
   485  		}
   486  
   487  		if stmt.prepared || stmt.paramCount > 0 {
   488  			if err = stmt.prepare(); err != nil {
   489  				continue
   490  			}
   491  		}
   492  
   493  		dc.stmtMap[stmt.id] = stmt
   494  	}
   495  
   496  	return nil
   497  }
   498  
   499  func (dc *DmConnection) cleanup() {
   500  	dc.close()
   501  }
   502  
   503  func (dc *DmConnection) close() error {
   504  	if !dc.closed.TrySet(true) {
   505  		return nil
   506  	}
   507  
   508  	util.AbsorbPanic(func() {
   509  		close(dc.closech)
   510  	})
   511  	if dc.Access == nil {
   512  		return nil
   513  	}
   514  
   515  	dc.rollback()
   516  
   517  	for _, stmt := range dc.stmtMap {
   518  		stmt.free()
   519  	}
   520  
   521  	dc.Access.Close()
   522  
   523  	return nil
   524  }
   525  
   526  func (dc *DmConnection) ping(ctx context.Context) error {
   527  	if err := dc.watchCancel(ctx); err != nil {
   528  		return err
   529  	}
   530  	defer dc.finish()
   531  
   532  	rows, err := dc.query("select 1", nil)
   533  	if err != nil {
   534  		return err
   535  	}
   536  	return rows.close()
   537  }
   538  
   539  func (dc *DmConnection) exec(query string, args []driver.Value) (*DmResult, error) {
   540  	err := dc.checkClosed()
   541  	if err != nil {
   542  		return nil, err
   543  	}
   544  
   545  	if args != nil && len(args) > 0 {
   546  		stmt, err := dc.prepare(query)
   547  		defer stmt.close()
   548  		if err != nil {
   549  			return nil, err
   550  		}
   551  		dc.lastExecInfo = stmt.execInfo
   552  
   553  		return stmt.exec(args)
   554  	} else {
   555  		r1, err := dc.executeInner(query, Dm_build_97)
   556  		if err != nil {
   557  			return nil, err
   558  		}
   559  
   560  		if r2, ok := r1.(*DmResult); ok {
   561  			return r2, nil
   562  		} else {
   563  			return nil, ECGO_NOT_EXEC_SQL.throw()
   564  		}
   565  	}
   566  }
   567  
   568  func (dc *DmConnection) execContext(ctx context.Context, query string, args []driver.NamedValue) (*DmResult, error) {
   569  	if err := dc.watchCancel(ctx); err != nil {
   570  		return nil, err
   571  	}
   572  	defer dc.finish()
   573  
   574  	err := dc.checkClosed()
   575  	if err != nil {
   576  		return nil, err
   577  	}
   578  
   579  	if args != nil && len(args) > 0 {
   580  		stmt, err := dc.prepare(query)
   581  		defer stmt.close()
   582  		if err != nil {
   583  			return nil, err
   584  		}
   585  		dc.lastExecInfo = stmt.execInfo
   586  		dargs, err := namedValueToValue(stmt, args)
   587  		if err != nil {
   588  			return nil, err
   589  		}
   590  		return stmt.exec(dargs)
   591  	} else {
   592  		r1, err := dc.executeInner(query, Dm_build_97)
   593  		if err != nil {
   594  			return nil, err
   595  		}
   596  
   597  		if r2, ok := r1.(*DmResult); ok {
   598  			return r2, nil
   599  		} else {
   600  			return nil, ECGO_NOT_EXEC_SQL.throw()
   601  		}
   602  	}
   603  }
   604  
   605  func (dc *DmConnection) query(query string, args []driver.Value) (*DmRows, error) {
   606  
   607  	err := dc.checkClosed()
   608  	if err != nil {
   609  		return nil, err
   610  	}
   611  
   612  	if args != nil && len(args) > 0 {
   613  		stmt, err := dc.prepare(query)
   614  		if err != nil {
   615  			stmt.close()
   616  			return nil, err
   617  		}
   618  		dc.lastExecInfo = stmt.execInfo
   619  
   620  		stmt.innerUsed = true
   621  		return stmt.query(args)
   622  
   623  	} else {
   624  		r1, err := dc.executeInner(query, Dm_build_96)
   625  		if err != nil {
   626  			return nil, err
   627  		}
   628  
   629  		if r2, ok := r1.(*DmRows); ok {
   630  			return r2, nil
   631  		} else {
   632  			return nil, ECGO_NOT_QUERY_SQL.throw()
   633  		}
   634  	}
   635  }
   636  
   637  func (dc *DmConnection) queryContext(ctx context.Context, query string, args []driver.NamedValue) (*DmRows, error) {
   638  	if err := dc.watchCancel(ctx); err != nil {
   639  		return nil, err
   640  	}
   641  	defer dc.finish()
   642  
   643  	err := dc.checkClosed()
   644  	if err != nil {
   645  		return nil, err
   646  	}
   647  
   648  	if args != nil && len(args) > 0 {
   649  		stmt, err := dc.prepare(query)
   650  		if err != nil {
   651  			if stmt != nil {
   652  				stmt.close()
   653  			}
   654  			return nil, err
   655  		}
   656  		dc.lastExecInfo = stmt.execInfo
   657  
   658  		stmt.innerUsed = true
   659  		dargs, err := namedValueToValue(stmt, args)
   660  		if err != nil {
   661  			return nil, err
   662  		}
   663  		return stmt.query(dargs)
   664  
   665  	} else {
   666  		r1, err := dc.executeInner(query, Dm_build_96)
   667  		if err != nil {
   668  			return nil, err
   669  		}
   670  
   671  		if r2, ok := r1.(*DmRows); ok {
   672  			return r2, nil
   673  		} else {
   674  			return nil, ECGO_NOT_QUERY_SQL.throw()
   675  		}
   676  	}
   677  
   678  }
   679  
   680  func (dc *DmConnection) prepare(query string) (stmt *DmStatement, err error) {
   681  	if err = dc.checkClosed(); err != nil {
   682  		return
   683  	}
   684  	if stmt, err = NewDmStmt(dc, query); err != nil {
   685  		return
   686  	}
   687  	err = stmt.prepare()
   688  	return
   689  }
   690  
   691  func (dc *DmConnection) prepareContext(ctx context.Context, query string) (*DmStatement, error) {
   692  	if err := dc.watchCancel(ctx); err != nil {
   693  		return nil, err
   694  	}
   695  	defer dc.finish()
   696  
   697  	return dc.prepare(query)
   698  }
   699  
   700  func (dc *DmConnection) resetSession(ctx context.Context) error {
   701  	if err := dc.watchCancel(ctx); err != nil {
   702  		return err
   703  	}
   704  	defer dc.finish()
   705  
   706  	err := dc.checkClosed()
   707  	if err != nil {
   708  		return err
   709  	}
   710  
   711  	return nil
   712  }
   713  
   714  func (dc *DmConnection) checkNamedValue(nv *driver.NamedValue) error {
   715  	var err error
   716  	var cvt = converter{dc, false}
   717  	nv.Value, err = cvt.ConvertValue(nv.Value)
   718  	dc.isBatch = cvt.isBatch
   719  	return err
   720  }
   721  
   722  func (dc *DmConnection) driverQuery(query string) (*DmStatement, *DmRows, error) {
   723  	stmt, err := NewDmStmt(dc, query)
   724  	if err != nil {
   725  		return nil, nil, err
   726  	}
   727  	stmt.innerUsed = true
   728  	stmt.innerExec = true
   729  	info, err := dc.Access.Dm_build_1431(stmt, Dm_build_96)
   730  	if err != nil {
   731  		return nil, nil, err
   732  	}
   733  	dc.lastExecInfo = info
   734  	stmt.innerExec = false
   735  	return stmt, newDmRows(newInnerRows(0, stmt, info)), nil
   736  }
   737  
   738  func (dc *DmConnection) getIndexOnEPGroup() int32 {
   739  	if dc.dmConnector.group == nil || dc.dmConnector.group.epList == nil {
   740  		return -1
   741  	}
   742  	for i := 0; i < len(dc.dmConnector.group.epList); i++ {
   743  		ep := dc.dmConnector.group.epList[i]
   744  		if dc.dmConnector.host == ep.host && dc.dmConnector.port == ep.port {
   745  			return int32(i)
   746  		}
   747  	}
   748  	return -1
   749  }
   750  
   751  func (dc *DmConnection) getServerEncoding() string {
   752  	if dc.dmConnector.charCode != "" {
   753  		return dc.dmConnector.charCode
   754  	}
   755  	return dc.serverEncoding
   756  }
   757  
   758  func (dc *DmConnection) lobFetchAll() bool {
   759  	return dc.dmConnector.lobMode == 2
   760  }
   761  
   762  func (conn *DmConnection) CompatibleOracle() bool {
   763  	return conn.dmConnector.compatibleMode == COMPATIBLE_MODE_ORACLE
   764  }
   765  
   766  func (conn *DmConnection) CompatibleMysql() bool {
   767  	return conn.dmConnector.compatibleMode == COMPATIBLE_MODE_MYSQL
   768  }
   769  
   770  func (conn *DmConnection) cancel(err error) {
   771  	conn.canceled.Set(err)
   772  	conn.close()
   773  
   774  }
   775  
   776  func (conn *DmConnection) finish() {
   777  	if !conn.watching || conn.finished == nil {
   778  		return
   779  	}
   780  	select {
   781  	case conn.finished <- struct{}{}:
   782  		conn.watching = false
   783  	case <-conn.closech:
   784  	}
   785  }
   786  
   787  func (conn *DmConnection) startWatcher() {
   788  	watcher := make(chan context.Context, 1)
   789  	conn.watcher = watcher
   790  	finished := make(chan struct{})
   791  	conn.finished = finished
   792  	go func() {
   793  		for {
   794  			var ctx context.Context
   795  			select {
   796  			case ctx = <-watcher:
   797  			case <-conn.closech:
   798  				return
   799  			}
   800  
   801  			select {
   802  			case <-ctx.Done():
   803  				conn.cancel(ctx.Err())
   804  			case <-finished:
   805  			case <-conn.closech:
   806  				return
   807  			}
   808  		}
   809  	}()
   810  }
   811  
   812  func (conn *DmConnection) watchCancel(ctx context.Context) error {
   813  	if conn.watching {
   814  
   815  		conn.cleanup()
   816  		return nil
   817  	}
   818  
   819  	if err := ctx.Err(); err != nil {
   820  		return err
   821  	}
   822  
   823  	if ctx.Done() == nil {
   824  		return nil
   825  	}
   826  
   827  	if conn.watcher == nil {
   828  		return nil
   829  	}
   830  
   831  	conn.watching = true
   832  	conn.watcher <- ctx
   833  	return nil
   834  }
   835  
   836  type noCopy struct{}
   837  
   838  func (*noCopy) Lock() {}
   839  
   840  type atomicBool struct {
   841  	_noCopy noCopy
   842  	value   uint32
   843  }
   844  
   845  func (ab *atomicBool) IsSet() bool {
   846  	return atomic.LoadUint32(&ab.value) > 0
   847  }
   848  
   849  func (ab *atomicBool) Set(value bool) {
   850  	if value {
   851  		atomic.StoreUint32(&ab.value, 1)
   852  	} else {
   853  		atomic.StoreUint32(&ab.value, 0)
   854  	}
   855  }
   856  
   857  func (ab *atomicBool) TrySet(value bool) bool {
   858  	if value {
   859  		return atomic.SwapUint32(&ab.value, 1) == 0
   860  	}
   861  	return atomic.SwapUint32(&ab.value, 0) > 0
   862  }
   863  
   864  type atomicError struct {
   865  	_noCopy noCopy
   866  	value   atomic.Value
   867  }
   868  
   869  func (ae *atomicError) Set(value error) {
   870  	ae.value.Store(value)
   871  }
   872  
   873  func (ae *atomicError) Value() error {
   874  	if v := ae.value.Load(); v != nil {
   875  
   876  		return v.(error)
   877  	}
   878  	return nil
   879  }