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

     1  /*
     2   * Copyright (c) 2000-2018, 达梦数据库有限公司.
     3   * All rights reserved.
     4   */
     5  package dmr
     6  
     7  import (
     8  	"bytes"
     9  	"context"
    10  	"database/sql"
    11  	"database/sql/driver"
    12  	"fmt"
    13  	"sync/atomic"
    14  
    15  	"github.com/wanlay/gorm-dm8/dmr/parser"
    16  	"golang.org/x/text/encoding"
    17  )
    18  
    19  type DmConnection struct {
    20  	filterable
    21  
    22  	dmConnector        *DmConnector
    23  	Access             *dm_build_332
    24  	stmtMap            map[int32]*DmStatement
    25  	stmtPool           []stmtPoolInfo
    26  	lastExecInfo       *execRetInfo
    27  	lexer              *parser.Lexer
    28  	encode             encoding.Encoding
    29  	encodeBuffer       *bytes.Buffer
    30  	transformReaderDst []byte
    31  	transformReaderSrc []byte
    32  
    33  	serverEncoding     string
    34  	GlobalServerSeries int
    35  	ServerVersion      string
    36  	Malini2            bool
    37  	Execute2           bool
    38  	LobEmptyCompOrcl   bool
    39  	IsoLevel           int32
    40  	ReadOnly           bool
    41  	NewLobFlag         bool
    42  	sslEncrypt         int
    43  	MaxRowSize         int32
    44  	DDLAutoCommit      bool
    45  	BackslashEscape    bool
    46  	SvrStat            int32
    47  	SvrMode            int32
    48  	ConstParaOpt       bool
    49  	DbTimezone         int16
    50  	LifeTimeRemainder  int16
    51  	InstanceName       string
    52  	Schema             string
    53  	LastLoginIP        string
    54  	LastLoginTime      string
    55  	FailedAttempts     int32
    56  	LoginWarningID     int32
    57  	GraceTimeRemainder int32
    58  	Guid               string
    59  	DbName             string
    60  	StandbyHost        string
    61  	StandbyPort        int32
    62  	StandbyCount       int32
    63  	SessionID          int64
    64  	OracleDateLanguage byte
    65  	FormatDate         string
    66  	FormatTimestamp    string
    67  	FormatTimestampTZ  string
    68  	FormatTime         string
    69  	FormatTimeTZ       string
    70  	Local              bool
    71  	MsgVersion         int32
    72  	TrxStatus          int32
    73  	dscControl         bool
    74  	trxFinish          bool
    75  	sessionID          int64
    76  	autoCommit         bool
    77  	isBatch            bool
    78  
    79  	watching bool
    80  	watcher  chan<- context.Context
    81  	closech  chan struct{}
    82  	finished chan<- struct{}
    83  	canceled atomicError
    84  	closed   atomicBool
    85  }
    86  
    87  func (conn *DmConnection) setTrxFinish(status int32) {
    88  	switch status & Dm_build_722 {
    89  	case Dm_build_719, Dm_build_720, Dm_build_721:
    90  		conn.trxFinish = true
    91  	default:
    92  		conn.trxFinish = false
    93  	}
    94  }
    95  
    96  func (dmConn *DmConnection) init() {
    97  	if dmConn.dmConnector.stmtPoolMaxSize > 0 {
    98  		dmConn.stmtPool = make([]stmtPoolInfo, 0, dmConn.dmConnector.stmtPoolMaxSize)
    99  	}
   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.sessionID = -1
   111  	dmConn.Malini2 = true
   112  	dmConn.NewLobFlag = true
   113  	dmConn.Execute2 = true
   114  	dmConn.serverEncoding = ENCODING_GB18030
   115  	dmConn.TrxStatus = Dm_build_670
   116  	dmConn.OracleDateLanguage = byte(Locale)
   117  	dmConn.lastExecInfo = NewExceInfo()
   118  	dmConn.MsgVersion = Dm_build_603
   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.sessionID = -1
   133  	dmConn.Malini2 = true
   134  	dmConn.NewLobFlag = true
   135  	dmConn.Execute2 = true
   136  	dmConn.serverEncoding = ENCODING_GB18030
   137  	dmConn.TrxStatus = Dm_build_670
   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_687 {
   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_686 && 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_411(stmt, optParamList)
   197  		if err != nil {
   198  			stmt.nativeSql = query
   199  			info, err = dc.Access.Dm_build_417(stmt, execType)
   200  		}
   201  	} else {
   202  		info, err = dc.Access.Dm_build_417(stmt, execType)
   203  	}
   204  
   205  	if err != nil {
   206  		stmt.close()
   207  		return nil, err
   208  	}
   209  	dc.lastExecInfo = info
   210  
   211  	if 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_674
   222  	case 2:
   223  		return Dm_build_675
   224  	case 4:
   225  		return Dm_build_676
   226  	case 6:
   227  		return Dm_build_677
   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  	return dc.filterChain.reset().DmConnectionResetSession(dc, ctx)
   327  }
   328  
   329  func (dc *DmConnection) CheckNamedValue(nv *driver.NamedValue) error {
   330  	if len(dc.filterChain.filters) == 0 {
   331  		return dc.checkNamedValue(nv)
   332  	}
   333  	return dc.filterChain.reset().DmConnectionCheckNamedValue(dc, nv)
   334  }
   335  
   336  func (dc *DmConnection) begin() (*DmConnection, error) {
   337  	return dc.beginTx(context.Background(), driver.TxOptions{driver.IsolationLevel(sql.LevelDefault), false})
   338  }
   339  
   340  func (dc *DmConnection) beginTx(ctx context.Context, opts driver.TxOptions) (*DmConnection, error) {
   341  	if err := dc.watchCancel(ctx); err != nil {
   342  		return nil, err
   343  	}
   344  	defer dc.finish()
   345  
   346  	err := dc.checkClosed()
   347  	if err != nil {
   348  		return nil, err
   349  	}
   350  
   351  	dc.autoCommit = false
   352  
   353  	if sql.IsolationLevel(opts.Isolation) == sql.LevelDefault {
   354  		opts.Isolation = driver.IsolationLevel(sql.LevelReadCommitted)
   355  	}
   356  
   357  	dc.ReadOnly = opts.ReadOnly
   358  
   359  	if dc.IsoLevel == int32(opts.Isolation) {
   360  		return dc, nil
   361  	}
   362  
   363  	switch sql.IsolationLevel(opts.Isolation) {
   364  	case sql.LevelDefault, sql.LevelReadUncommitted:
   365  		return dc, nil
   366  	case sql.LevelReadCommitted, sql.LevelSerializable:
   367  		dc.IsoLevel = int32(opts.Isolation)
   368  	case sql.LevelRepeatableRead:
   369  		if dc.CompatibleMysql() {
   370  			dc.IsoLevel = int32(sql.LevelReadCommitted)
   371  		} else {
   372  			return nil, ECGO_INVALID_TRAN_ISOLATION.throw()
   373  		}
   374  	default:
   375  		return nil, ECGO_INVALID_TRAN_ISOLATION.throw()
   376  	}
   377  
   378  	err = dc.Access.Dm_build_471(dc)
   379  	if err != nil {
   380  		return nil, err
   381  	}
   382  	return dc, nil
   383  }
   384  
   385  func (dc *DmConnection) commit() error {
   386  	err := dc.checkClosed()
   387  	if err != nil {
   388  		return err
   389  	}
   390  
   391  	defer func() {
   392  		dc.autoCommit = dc.dmConnector.autoCommit
   393  	}()
   394  
   395  	if !dc.autoCommit {
   396  		err = dc.Access.Commit()
   397  		if err != nil {
   398  			return err
   399  		}
   400  		dc.trxFinish = true
   401  		return nil
   402  	} else if !dc.dmConnector.alwayseAllowCommit {
   403  		return ECGO_COMMIT_IN_AUTOCOMMIT_MODE.throw()
   404  	}
   405  
   406  	return nil
   407  }
   408  
   409  func (dc *DmConnection) rollback() error {
   410  	err := dc.checkClosed()
   411  	if err != nil {
   412  		return err
   413  	}
   414  
   415  	defer func() {
   416  		dc.autoCommit = dc.dmConnector.autoCommit
   417  	}()
   418  
   419  	if !dc.autoCommit {
   420  		err = dc.Access.Rollback()
   421  		if err != nil {
   422  			return err
   423  		}
   424  		dc.trxFinish = true
   425  		return nil
   426  	} else if !dc.dmConnector.alwayseAllowCommit {
   427  		return ECGO_ROLLBACK_IN_AUTOCOMMIT_MODE.throw()
   428  	}
   429  
   430  	return nil
   431  }
   432  
   433  func (dc *DmConnection) reconnect() error {
   434  	err := dc.Access.Close()
   435  	if err != nil {
   436  		return err
   437  	}
   438  
   439  	for _, stmt := range dc.stmtMap {
   440  		stmt.closed = true
   441  		for id, _ := range stmt.rsMap {
   442  			delete(stmt.rsMap, id)
   443  		}
   444  	}
   445  
   446  	if dc.stmtPool != nil {
   447  		dc.stmtPool = dc.stmtPool[:0]
   448  	}
   449  
   450  	dc.dmConnector.reConnection = dc
   451  
   452  	if dc.dmConnector.group != nil {
   453  		_, err = dc.dmConnector.group.connect(dc.dmConnector)
   454  		if err != nil {
   455  			return err
   456  		}
   457  	} else {
   458  		_, err = dc.dmConnector.connect(context.Background())
   459  	}
   460  
   461  	for _, stmt := range dc.stmtMap {
   462  		err = dc.Access.Dm_build_389(stmt)
   463  		if err != nil {
   464  			return err
   465  		}
   466  
   467  		if stmt.paramCount > 0 {
   468  			err = stmt.prepare()
   469  			if err != nil {
   470  				return err
   471  			}
   472  		}
   473  	}
   474  
   475  	return nil
   476  }
   477  
   478  func (dc *DmConnection) cleanup() {
   479  	dc.close()
   480  }
   481  
   482  func (dc *DmConnection) close() error {
   483  	if !dc.closed.TrySet(true) {
   484  		return nil
   485  	}
   486  
   487  	close(dc.closech)
   488  	if dc.Access == nil {
   489  		return nil
   490  	}
   491  
   492  	dc.rollback()
   493  
   494  	for _, stmt := range dc.stmtMap {
   495  		stmt.free()
   496  	}
   497  
   498  	if dc.stmtPool != nil {
   499  		for _, spi := range dc.stmtPool {
   500  			dc.Access.Dm_build_394(spi.id)
   501  		}
   502  		dc.stmtPool = nil
   503  	}
   504  
   505  	dc.Access.Close()
   506  
   507  	return nil
   508  }
   509  
   510  func (dc *DmConnection) ping(ctx context.Context) error {
   511  	if err := dc.watchCancel(ctx); err != nil {
   512  		return err
   513  	}
   514  	defer dc.finish()
   515  
   516  	rows, err := dc.query("select 1", nil)
   517  	if err != nil {
   518  		return err
   519  	}
   520  	return rows.close()
   521  }
   522  
   523  func (dc *DmConnection) exec(query string, args []driver.Value) (*DmResult, error) {
   524  	err := dc.checkClosed()
   525  	if err != nil {
   526  		return nil, err
   527  	}
   528  
   529  	if args != nil && len(args) > 0 {
   530  		stmt, err := dc.prepare(query)
   531  		defer stmt.close()
   532  		if err != nil {
   533  			return nil, err
   534  		}
   535  		dc.lastExecInfo = stmt.execInfo
   536  
   537  		return stmt.exec(args)
   538  	} else {
   539  		r1, err := dc.executeInner(query, Dm_build_687)
   540  		if err != nil {
   541  			return nil, err
   542  		}
   543  
   544  		if r2, ok := r1.(*DmResult); ok {
   545  			return r2, nil
   546  		} else {
   547  			return nil, ECGO_NOT_EXEC_SQL.throw()
   548  		}
   549  	}
   550  }
   551  
   552  func (dc *DmConnection) execContext(ctx context.Context, query string, args []driver.NamedValue) (*DmResult, error) {
   553  
   554  	if err := dc.watchCancel(ctx); err != nil {
   555  		return nil, err
   556  	}
   557  	defer dc.finish()
   558  
   559  	err := dc.checkClosed()
   560  	if err != nil {
   561  		return nil, err
   562  	}
   563  
   564  	if args != nil && len(args) > 0 {
   565  		stmt, err := dc.prepare(query)
   566  		defer stmt.close()
   567  		if err != nil {
   568  			return nil, err
   569  		}
   570  		dc.lastExecInfo = stmt.execInfo
   571  
   572  		return stmt.execContext(ctx, args)
   573  	} else {
   574  		r1, err := dc.executeInner(query, Dm_build_687)
   575  		if err != nil {
   576  			return nil, err
   577  		}
   578  
   579  		if r2, ok := r1.(*DmResult); ok {
   580  			return r2, nil
   581  		} else {
   582  			return nil, ECGO_NOT_EXEC_SQL.throw()
   583  		}
   584  	}
   585  }
   586  
   587  func (dc *DmConnection) query(query string, args []driver.Value) (*DmRows, error) {
   588  
   589  	err := dc.checkClosed()
   590  	if err != nil {
   591  		return nil, err
   592  	}
   593  
   594  	if args != nil && len(args) > 0 {
   595  		stmt, err := dc.prepare(query)
   596  		if err != nil {
   597  			stmt.close()
   598  			return nil, err
   599  		}
   600  		dc.lastExecInfo = stmt.execInfo
   601  
   602  		stmt.innerUsed = true
   603  		return stmt.query(args)
   604  
   605  	} else {
   606  		r1, err := dc.executeInner(query, Dm_build_686)
   607  		if err != nil {
   608  			return nil, err
   609  		}
   610  
   611  		if r2, ok := r1.(*DmRows); ok {
   612  			return r2, nil
   613  		} else {
   614  			return nil, ECGO_NOT_QUERY_SQL.throw()
   615  		}
   616  	}
   617  }
   618  
   619  func (dc *DmConnection) queryContext(ctx context.Context, query string, args []driver.NamedValue) (*DmRows, error) {
   620  	if err := dc.watchCancel(ctx); err != nil {
   621  		return nil, err
   622  	}
   623  	defer dc.finish()
   624  
   625  	err := dc.checkClosed()
   626  	if err != nil {
   627  		return nil, err
   628  	}
   629  
   630  	if args != nil && len(args) > 0 {
   631  		stmt, err := dc.prepare(query)
   632  		if err != nil {
   633  			stmt.close()
   634  			return nil, err
   635  		}
   636  		dc.lastExecInfo = stmt.execInfo
   637  
   638  		stmt.innerUsed = true
   639  		return stmt.queryContext(ctx, args)
   640  
   641  	} else {
   642  		r1, err := dc.executeInner(query, Dm_build_686)
   643  		if err != nil {
   644  			return nil, err
   645  		}
   646  
   647  		if r2, ok := r1.(*DmRows); ok {
   648  			return r2, nil
   649  		} else {
   650  			return nil, ECGO_NOT_QUERY_SQL.throw()
   651  		}
   652  	}
   653  
   654  }
   655  
   656  func (dc *DmConnection) prepare(query string) (*DmStatement, error) {
   657  	err := dc.checkClosed()
   658  	if err != nil {
   659  		return nil, err
   660  	}
   661  
   662  	stmt, err := NewDmStmt(dc, query)
   663  	if err != nil {
   664  		return nil, err
   665  	}
   666  
   667  	err = stmt.prepare()
   668  	return stmt, err
   669  }
   670  
   671  func (dc *DmConnection) prepareContext(ctx context.Context, query string) (*DmStatement, error) {
   672  	if err := dc.watchCancel(ctx); err != nil {
   673  		return nil, err
   674  	}
   675  	defer dc.finish()
   676  
   677  	err := dc.checkClosed()
   678  	if err != nil {
   679  		return nil, err
   680  	}
   681  
   682  	stmt, err := dc.prepare(query)
   683  	if err != nil {
   684  		return nil, err
   685  	}
   686  
   687  	return stmt, nil
   688  }
   689  
   690  func (dc *DmConnection) resetSession(ctx context.Context) error {
   691  	err := dc.checkClosed()
   692  	if err != nil {
   693  		return err
   694  	}
   695  
   696  	for _, stmt := range dc.stmtMap {
   697  		stmt.inUse = false
   698  	}
   699  
   700  	return nil
   701  }
   702  
   703  func (dc *DmConnection) checkNamedValue(nv *driver.NamedValue) error {
   704  	var err error
   705  	var cvt = converter{dc, false}
   706  	nv.Value, err = cvt.ConvertValue(nv.Value)
   707  	dc.isBatch = cvt.isBatch
   708  	return err
   709  }
   710  
   711  func (dc *DmConnection) driverQuery(query string) (*DmStatement, *DmRows, error) {
   712  	stmt, err := NewDmStmt(dc, query)
   713  	if err != nil {
   714  		return nil, nil, err
   715  	}
   716  	stmt.innerUsed = true
   717  	stmt.innerExec = true
   718  	info, err := dc.Access.Dm_build_417(stmt, Dm_build_686)
   719  	if err != nil {
   720  		return nil, nil, err
   721  	}
   722  	dc.lastExecInfo = info
   723  	stmt.innerExec = false
   724  	return stmt, newDmRows(newInnerRows(0, stmt, info)), nil
   725  }
   726  
   727  func (dc *DmConnection) getIndexOnEPGroup() int32 {
   728  	if dc.dmConnector.group == nil || dc.dmConnector.group.epList == nil {
   729  		return -1
   730  	}
   731  	for i := 0; i < len(dc.dmConnector.group.epList); i++ {
   732  		ep := dc.dmConnector.group.epList[i]
   733  		if dc.dmConnector.host == ep.host && dc.dmConnector.port == ep.port {
   734  			return int32(i)
   735  		}
   736  	}
   737  	return -1
   738  }
   739  
   740  func (dc *DmConnection) getServerEncoding() string {
   741  	if dc.dmConnector.charCode != "" {
   742  		return dc.dmConnector.charCode
   743  	}
   744  	return dc.serverEncoding
   745  }
   746  
   747  func (dc *DmConnection) lobFetchAll() bool {
   748  	return dc.dmConnector.lobMode == 2
   749  }
   750  
   751  func (conn *DmConnection) CompatibleOracle() bool {
   752  	return conn.dmConnector.compatibleMode == COMPATIBLE_MODE_ORACLE
   753  }
   754  
   755  func (conn *DmConnection) CompatibleMysql() bool {
   756  	return conn.dmConnector.compatibleMode == COMPATIBLE_MODE_MYSQL
   757  }
   758  
   759  func (conn *DmConnection) cancel(err error) {
   760  	conn.canceled.Set(err)
   761  	fmt.Println(conn.close())
   762  }
   763  
   764  func (conn *DmConnection) finish() {
   765  	if !conn.watching || conn.finished == nil {
   766  		return
   767  	}
   768  	select {
   769  	case conn.finished <- struct{}{}:
   770  		conn.watching = false
   771  	case <-conn.closech:
   772  	}
   773  }
   774  
   775  func (conn *DmConnection) startWatcher() {
   776  	watcher := make(chan context.Context, 1)
   777  	conn.watcher = watcher
   778  	finished := make(chan struct{})
   779  	conn.finished = finished
   780  	go func() {
   781  		for {
   782  			var ctx context.Context
   783  			select {
   784  			case ctx = <-watcher:
   785  			case <-conn.closech:
   786  				return
   787  			}
   788  
   789  			select {
   790  			case <-ctx.Done():
   791  				conn.cancel(ctx.Err())
   792  			case <-finished:
   793  			case <-conn.closech:
   794  				return
   795  			}
   796  		}
   797  	}()
   798  }
   799  
   800  func (conn *DmConnection) watchCancel(ctx context.Context) error {
   801  	if conn.watching {
   802  
   803  		conn.cleanup()
   804  		return nil
   805  	}
   806  
   807  	if err := ctx.Err(); err != nil {
   808  		return err
   809  	}
   810  
   811  	if ctx.Done() == nil {
   812  		return nil
   813  	}
   814  
   815  	if conn.watcher == nil {
   816  		return nil
   817  	}
   818  
   819  	conn.watching = true
   820  	conn.watcher <- ctx
   821  	return nil
   822  }
   823  
   824  type noCopy struct{}
   825  
   826  func (*noCopy) Lock() {}
   827  
   828  type atomicBool struct {
   829  	_noCopy noCopy
   830  	value   uint32
   831  }
   832  
   833  func (ab *atomicBool) IsSet() bool {
   834  	return atomic.LoadUint32(&ab.value) > 0
   835  }
   836  
   837  func (ab *atomicBool) Set(value bool) {
   838  	if value {
   839  		atomic.StoreUint32(&ab.value, 1)
   840  	} else {
   841  		atomic.StoreUint32(&ab.value, 0)
   842  	}
   843  }
   844  
   845  func (ab *atomicBool) TrySet(value bool) bool {
   846  	if value {
   847  		return atomic.SwapUint32(&ab.value, 1) == 0
   848  	}
   849  	return atomic.SwapUint32(&ab.value, 0) > 0
   850  }
   851  
   852  type atomicError struct {
   853  	_noCopy noCopy
   854  	value   atomic.Value
   855  }
   856  
   857  func (ae *atomicError) Set(value error) {
   858  	ae.value.Store(value)
   859  }
   860  
   861  func (ae *atomicError) Value() error {
   862  	if v := ae.value.Load(); v != nil {
   863  
   864  		return v.(error)
   865  	}
   866  	return nil
   867  }