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