github.com/xiyichan/dm8@v0.0.0-20211213021639-be727be3e136/p.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/driver"
    11  	"github.com/xiyichan/dm8/util"
    12  	"net"
    13  	"net/url"
    14  	"os"
    15  	"path/filepath"
    16  	"runtime"
    17  	"strconv"
    18  	"strings"
    19  )
    20  
    21  const (
    22  	TimeZoneKey              = "timeZone"
    23  	EnRsCacheKey             = "enRsCache"
    24  	RsCacheSizeKey           = "rsCacheSize"
    25  	RsRefreshFreqKey         = "rsRefreshFreq"
    26  	LoginPrimary             = "loginPrimary"
    27  	LoginModeKey             = "loginMode"
    28  	LoginStatusKey           = "loginStatus"
    29  	SwitchTimesKey           = "switchTimes"
    30  	SwitchIntervalKey        = "switchInterval"
    31  	PrimaryKey               = "primaryKey"
    32  	KeywordsKey              = "keywords"
    33  	CompressKey              = "compress"
    34  	CompressIdKey            = "compressId"
    35  	LoginEncryptKey          = "loginEncrypt"
    36  	CommunicationEncryptKey  = "communicationEncrypt"
    37  	DirectKey                = "direct"
    38  	Dec2DoubleKey            = "dec2double"
    39  	RwSeparateKey            = "rwSeparate"
    40  	RwPercentKey             = "rwPercent"
    41  	RwAutoDistributeKey      = "rwAutoDistribute"
    42  	CompatibleModeKey        = "compatibleMode"
    43  	CompatibleOraKey         = "comOra"
    44  	CipherPathKey            = "cipherPath"
    45  	DoSwitchKey              = "doSwitch"
    46  	LanguageKey              = "language"
    47  	DbAliveCheckFreqKey      = "dbAliveCheckFreq"
    48  	RwStandbyRecoverTimeKey  = "rwStandbyRecoverTime"
    49  	LogLevelKey              = "logLevel"
    50  	LogDirKey                = "logDir"
    51  	LogBufferPoolSizeKey     = "logBufferPoolSize"
    52  	LogBufferSizeKey         = "logBufferSize"
    53  	LogFlusherQueueSizeKey   = "logFlusherQueueSize"
    54  	LogFlushFreqKey          = "logFlushFreq"
    55  	StatEnableKey            = "statEnable"
    56  	StatDirKey               = "statDir"
    57  	StatFlushFreqKey         = "statFlushFreq"
    58  	StatHighFreqSqlCountKey  = "statHighFreqSqlCount"
    59  	StatSlowSqlCountKey      = "statSlowSqlCount"
    60  	StatSqlMaxCountKey       = "statSqlMaxCount"
    61  	StatSqlRemoveModeKey     = "statSqlRemoveMode"
    62  	AddressRemapKey          = "addressreMap"
    63  	UserreMapKey             = "userreMap"
    64  	ConnectTimeoutKey        = "connectTimeout"
    65  	LoginCertificateKey      = "loginCertificate"
    66  	UrlKey                   = "url"
    67  	HostKey                  = "host"
    68  	PortKey                  = "port"
    69  	UserKey                  = "user"
    70  	PasswordKey              = "password"
    71  	RwStandbyKey             = "rwStandby"
    72  	IsCompressKey            = "isCompress"
    73  	RwHAKey                  = "rwHA"
    74  	AppNameKey               = "appName"
    75  	MppLocalKey              = "mppLocal"
    76  	SocketTimeoutKey         = "socketTimeout"
    77  	SessionTimeoutKey        = "sessionTimeout"
    78  	ContinueBatchOnErrorKey  = "continueBatchOnError"
    79  	EscapeProcessKey         = "escapeProcess"
    80  	AutoCommitKey            = "autoCommit"
    81  	MaxRowsKey               = "maxRows"
    82  	RowPrefetchKey           = "rowPrefetch"
    83  	BufPrefetchKey           = "bufPrefetch"
    84  	LobModeKey               = "LobMode"
    85  	StmtPoolSizeKey          = "StmtPoolSize"
    86  	IgnoreCaseKey            = "ignoreCase"
    87  	AlwayseAllowCommitKey    = "AlwayseAllowCommit"
    88  	BatchTypeKey             = "batchType"
    89  	IsBdtaRSKey              = "isBdtaRS"
    90  	ClobAsStringKey          = "clobAsString"
    91  	CallBatchNotKey          = "callBatchNot"
    92  	SslCertPathKey           = "sslCertPath"
    93  	SslKeyPathKey            = "sslKeyPath"
    94  	SslFilesPathKey          = "sslFilesPath"
    95  	KerberosLoginConfPathKey = "kerberosLoginConfPath"
    96  	UKeyNameKey              = "uKeyName"
    97  	UKeyPinKey               = "uKeyPin"
    98  	ColumnNameUpperCaseKey   = "columnNameUpperCase"
    99  	ColumnNameCaseKey        = "columnNameCase"
   100  	DatabaseProductNameKey   = "databaseProductName"
   101  	OsAuthTypeKey            = "osAuthType"
   102  	SchemaKey                = "schema"
   103  
   104  	TIME_ZONE_DEFAULT int16 = 480
   105  
   106  	LOGIN_MODE_ALL_AND_PRIMARY_FIRST int = 0
   107  
   108  	LOGIN_MODE_PRIMARY int = 1
   109  
   110  	LOGIN_MODE_STANDBY int = 2
   111  
   112  	LOGIN_MODE_ALL_AND_STANDBY_FIRST int = 3
   113  
   114  	LOGIN_MODE_ALL_AND_NORMAL_FIRST int = 4
   115  
   116  	LOGIN_MODE_DEFAULT int = LOGIN_MODE_ALL_AND_PRIMARY_FIRST
   117  
   118  	SERVER_MODE_NORMAL int = 0
   119  
   120  	SERVER_MODE_PRIMARY int = 1
   121  
   122  	SERVER_MODE_STANDBY int = 2
   123  
   124  	SERVER_STATUS_OPEN int = 4
   125  
   126  	SERVER_STATUS_MOUNT int = 3
   127  
   128  	SERVER_STATUS_SUSPEND int = 5
   129  
   130  	COMPATIBLE_MODE_ORACLE int = 1
   131  
   132  	COMPATIBLE_MODE_MYSQL int = 2
   133  
   134  	LANGUAGE_CN int = 0
   135  
   136  	LANGUAGE_EN int = 1
   137  
   138  	COLUMN_NAME_UPPDER_CASE = 1
   139  
   140  	COLUMN_NAME_LOWER_CASE = 2
   141  
   142  	compressDef   = Dm_build_81
   143  	compressIDDef = Dm_build_82
   144  
   145  	charCodeDef = ""
   146  
   147  	enRsCacheDef = false
   148  
   149  	rsCacheSizeDef = 20
   150  
   151  	rsRefreshFreqDef = 10
   152  
   153  	loginModeDef = LOGIN_MODE_DEFAULT
   154  
   155  	loginStatusDef = 0
   156  
   157  	switchTimesDef = 3
   158  
   159  	switchIntervalDef = 2000
   160  
   161  	loginEncryptDef = true
   162  
   163  	loginCertificateDef = ""
   164  
   165  	dec2DoubleDef = false
   166  
   167  	rwHADef = false
   168  
   169  	rwStandbyDef = false
   170  
   171  	rwSeparateDef = false
   172  
   173  	rwPercentDef = 25
   174  
   175  	rwAutoDistributeDef = true
   176  
   177  	rwStandbyRecoverTimeDef = 1000
   178  
   179  	doSwitchDef = false
   180  
   181  	cipherPathDef = ""
   182  
   183  	urlDef = ""
   184  
   185  	userDef = "SYSDBA"
   186  
   187  	passwordDef = "SYSDBA"
   188  
   189  	hostDef = "localhost"
   190  
   191  	portDef = DEFAULT_PORT
   192  
   193  	appNameDef = ""
   194  
   195  	osNameDef = runtime.GOOS
   196  
   197  	mppLocalDef = false
   198  
   199  	socketTimeoutDef = 0
   200  
   201  	connectTimeoutDef = 5000
   202  
   203  	sessionTimeoutDef = 0
   204  
   205  	osAuthTypeDef = Dm_build_64
   206  
   207  	continueBatchOnErrorDef = false
   208  
   209  	escapeProcessDef = false
   210  
   211  	autoCommitDef = true
   212  
   213  	maxRowsDef = 0
   214  
   215  	rowPrefetchDef = Dm_build_65
   216  
   217  	bufPrefetchDef = 0
   218  
   219  	lobModeDef = 1
   220  
   221  	stmtPoolMaxSizeDef = 15
   222  
   223  	ignoreCaseDef = true
   224  
   225  	alwayseAllowCommitDef = true
   226  
   227  	batchTypeDef = 1
   228  
   229  	isBdtaRSDef = false
   230  
   231  	callBatchNotDef = false
   232  
   233  	kerberosLoginConfPathDef = ""
   234  
   235  	uKeyNameDef = ""
   236  
   237  	uKeyPinDef = ""
   238  
   239  	databaseProductNameDef = ""
   240  
   241  	columnNameCaseDef = 0
   242  
   243  	caseSensitiveDef = true
   244  
   245  	compatibleModeDef = 0
   246  
   247  	localTimezoneDef = TIME_ZONE_DEFAULT
   248  )
   249  
   250  type DmConnector struct {
   251  	filterable
   252  
   253  	dmDriver *DmDriver
   254  
   255  	compress int
   256  
   257  	compressID int8
   258  
   259  	charCode string
   260  
   261  	enRsCache bool
   262  
   263  	rsCacheSize int
   264  
   265  	rsRefreshFreq int
   266  
   267  	loginMode int
   268  
   269  	loginStatus int
   270  
   271  	switchTimes int
   272  
   273  	switchInterval int
   274  
   275  	keyWords []string
   276  
   277  	loginEncrypt bool
   278  
   279  	loginCertificate string
   280  
   281  	dec2Double bool
   282  
   283  	rwHA bool
   284  
   285  	rwStandby bool
   286  
   287  	rwSeparate bool
   288  
   289  	rwPercent int
   290  
   291  	rwAutoDistribute bool
   292  
   293  	rwStandbyRecoverTime int
   294  
   295  	doSwitch bool
   296  
   297  	cipherPath string
   298  
   299  	url string
   300  
   301  	user string
   302  
   303  	password string
   304  
   305  	host string
   306  
   307  	group *DBGroup
   308  
   309  	port int
   310  
   311  	appName string
   312  
   313  	osName string
   314  
   315  	mppLocal bool
   316  
   317  	socketTimeout int
   318  
   319  	connectTimeout int
   320  
   321  	sessionTimeout int
   322  
   323  	osAuthType byte
   324  
   325  	continueBatchOnError bool
   326  
   327  	escapeProcess bool
   328  
   329  	autoCommit bool
   330  
   331  	maxRows int
   332  
   333  	rowPrefetch int
   334  
   335  	bufPrefetch int
   336  
   337  	lobMode int
   338  
   339  	stmtPoolMaxSize int
   340  
   341  	ignoreCase bool
   342  
   343  	alwayseAllowCommit bool
   344  
   345  	batchType int
   346  
   347  	isBdtaRS bool
   348  
   349  	callBatchNot bool
   350  
   351  	sslCertPath string
   352  
   353  	sslKeyPath string
   354  
   355  	sslFilesPath string
   356  
   357  	kerberosLoginConfPath string
   358  
   359  	uKeyName string
   360  
   361  	uKeyPin string
   362  
   363  	svcConfPath string
   364  
   365  	columnNameCase int
   366  
   367  	caseSensitive bool
   368  
   369  	compatibleMode int
   370  
   371  	localTimezone int16
   372  
   373  	schema string
   374  
   375  	reConnection *DmConnection
   376  
   377  	logLevel int
   378  
   379  	logDir string
   380  
   381  	logFlushFreq int
   382  
   383  	logFlushQueueSize int
   384  
   385  	logBufferSize int
   386  
   387  	statEnable bool
   388  
   389  	statDir string
   390  
   391  	statFlushFreq int
   392  
   393  	statSlowSqlCount int
   394  
   395  	statHighFreqSqlCount int
   396  
   397  	statSqlMaxCount int
   398  
   399  	statSqlRemoveMode int
   400  }
   401  
   402  func (c *DmConnector) init() *DmConnector {
   403  	c.compress = compressDef
   404  	c.compressID = compressIDDef
   405  	c.charCode = charCodeDef
   406  	c.enRsCache = enRsCacheDef
   407  	c.rsCacheSize = rsCacheSizeDef
   408  	c.rsRefreshFreq = rsRefreshFreqDef
   409  	c.loginMode = loginModeDef
   410  	c.loginStatus = loginStatusDef
   411  	c.switchTimes = switchTimesDef
   412  	c.switchInterval = switchIntervalDef
   413  	c.keyWords = nil
   414  	c.loginEncrypt = loginEncryptDef
   415  	c.loginCertificate = loginCertificateDef
   416  	c.dec2Double = dec2DoubleDef
   417  	c.rwHA = rwHADef
   418  	c.rwStandby = rwStandbyDef
   419  	c.rwSeparate = rwSeparateDef
   420  	c.rwPercent = rwPercentDef
   421  	c.rwAutoDistribute = rwAutoDistributeDef
   422  	c.rwStandbyRecoverTime = rwStandbyRecoverTimeDef
   423  	c.doSwitch = doSwitchDef
   424  	c.cipherPath = cipherPathDef
   425  	c.url = urlDef
   426  	c.user = userDef
   427  	c.password = passwordDef
   428  	c.host = hostDef
   429  	c.port = portDef
   430  	c.appName = appNameDef
   431  	c.osName = osNameDef
   432  	c.mppLocal = mppLocalDef
   433  	c.socketTimeout = socketTimeoutDef
   434  	c.connectTimeout = connectTimeoutDef
   435  	c.sessionTimeout = sessionTimeoutDef
   436  	c.osAuthType = osAuthTypeDef
   437  	c.continueBatchOnError = continueBatchOnErrorDef
   438  	c.escapeProcess = escapeProcessDef
   439  	c.autoCommit = autoCommitDef
   440  	c.maxRows = maxRowsDef
   441  	c.rowPrefetch = rowPrefetchDef
   442  	c.bufPrefetch = bufPrefetchDef
   443  	c.lobMode = lobModeDef
   444  	c.stmtPoolMaxSize = stmtPoolMaxSizeDef
   445  	c.ignoreCase = ignoreCaseDef
   446  	c.alwayseAllowCommit = alwayseAllowCommitDef
   447  	c.batchType = batchTypeDef
   448  	c.isBdtaRS = isBdtaRSDef
   449  	c.callBatchNot = callBatchNotDef
   450  	c.kerberosLoginConfPath = kerberosLoginConfPathDef
   451  	c.uKeyName = uKeyNameDef
   452  	c.uKeyPin = uKeyPinDef
   453  	c.columnNameCase = columnNameCaseDef
   454  	c.caseSensitive = caseSensitiveDef
   455  	c.compatibleMode = compatibleModeDef
   456  	c.localTimezone = localTimezoneDef
   457  	c.idGenerator = dmConntorIDGenerator
   458  
   459  	c.logDir = LogDirDef
   460  	c.logFlushFreq = LogFlushFreqDef
   461  	c.logFlushQueueSize = LogFlushQueueSizeDef
   462  	c.logBufferSize = LogBufferSizeDef
   463  	c.statEnable = StatEnableDef
   464  	c.statDir = StatDirDef
   465  	c.statFlushFreq = StatFlushFreqDef
   466  	c.statSlowSqlCount = StatSlowSqlCountDef
   467  	c.statHighFreqSqlCount = StatHighFreqSqlCountDef
   468  	c.statSqlMaxCount = StatSqlMaxCountDef
   469  	c.statSqlRemoveMode = StatSqlRemoveModeDef
   470  	return c
   471  }
   472  
   473  func (c *DmConnector) setAttributes(props *Properties) error {
   474  	if props == nil || props.Len() == 0 {
   475  		return nil
   476  	}
   477  
   478  	c.url = props.GetTrimString(UrlKey, c.url)
   479  	c.host = props.GetTrimString(HostKey, c.host)
   480  	c.port = props.GetInt(PortKey, c.port, 0, 65535)
   481  	c.user = props.GetString(UserKey, c.user)
   482  	c.password = props.GetString(PasswordKey, c.password)
   483  	c.rwStandby = props.GetBool(RwStandbyKey, c.rwStandby)
   484  
   485  	if b := props.GetBool(IsCompressKey, false); b {
   486  		c.compress = Dm_build_80
   487  	}
   488  
   489  	c.compress = props.GetInt(CompressKey, c.compress, 0, 2)
   490  	c.compressID = int8(props.GetInt(CompressIdKey, int(c.compressID), -1, 1))
   491  	c.enRsCache = props.GetBool(EnRsCacheKey, c.enRsCache)
   492  	c.localTimezone = int16(props.GetInt(TimeZoneKey, int(c.localTimezone), -720, 720))
   493  	c.rsCacheSize = props.GetInt(RsCacheSizeKey, c.rsCacheSize, 0, int(INT32_MAX))
   494  	c.rsRefreshFreq = props.GetInt(RsRefreshFreqKey, c.rsRefreshFreq, 0, int(INT32_MAX))
   495  	c.loginMode = props.GetInt(LoginModeKey, c.loginMode, 0, 4)
   496  	c.loginStatus = props.GetInt(LoginStatusKey, c.loginStatus, 0, int(INT32_MAX))
   497  	c.switchTimes = props.GetInt(SwitchTimesKey, c.switchTimes, 0, int(INT32_MAX))
   498  	c.switchInterval = props.GetInt(SwitchIntervalKey, c.switchInterval, 0, int(INT32_MAX))
   499  	c.loginEncrypt = props.GetBool(LoginEncryptKey, c.loginEncrypt)
   500  	c.loginCertificate = props.GetTrimString(LoginCertificateKey, c.loginCertificate)
   501  	c.dec2Double = props.GetBool(Dec2DoubleKey, c.dec2Double)
   502  
   503  	c.rwSeparate = props.GetBool(RwSeparateKey, c.rwSeparate)
   504  	c.rwAutoDistribute = props.GetBool(RwAutoDistributeKey, c.rwAutoDistribute)
   505  	c.rwPercent = props.GetInt(RwPercentKey, c.rwPercent, 0, 100)
   506  	c.rwHA = props.GetBool(RwHAKey, c.rwHA)
   507  	c.rwStandbyRecoverTime = props.GetInt(RwStandbyRecoverTimeKey, c.rwStandbyRecoverTime, 0, int(INT32_MAX))
   508  	c.doSwitch = props.GetBool(DoSwitchKey, c.doSwitch)
   509  	c.cipherPath = props.GetTrimString(CipherPathKey, c.cipherPath)
   510  
   511  	if props.GetBool(CompatibleOraKey, false) {
   512  		c.compatibleMode = int(COMPATIBLE_MODE_ORACLE)
   513  	}
   514  	c.parseCompatibleMode(props)
   515  	c.keyWords = props.GetStringArray(KeywordsKey, c.keyWords)
   516  
   517  	c.appName = props.GetTrimString(AppNameKey, c.appName)
   518  	c.mppLocal = props.GetBool(MppLocalKey, c.mppLocal)
   519  	c.socketTimeout = props.GetInt(SocketTimeoutKey, c.socketTimeout, 0, int(INT32_MAX))
   520  	c.connectTimeout = props.GetInt(ConnectTimeoutKey, c.connectTimeout, 0, int(INT32_MAX))
   521  	c.sessionTimeout = props.GetInt(SessionTimeoutKey, c.sessionTimeout, 0, int(INT32_MAX))
   522  
   523  	err := c.parseOsAuthType(props)
   524  	if err != nil {
   525  		return err
   526  	}
   527  	c.continueBatchOnError = props.GetBool(ContinueBatchOnErrorKey,
   528  		c.continueBatchOnError)
   529  	c.escapeProcess = props.GetBool(EscapeProcessKey,
   530  		c.escapeProcess)
   531  	c.autoCommit = props.GetBool(AutoCommitKey, c.autoCommit)
   532  	c.maxRows = props.GetInt(MaxRowsKey, c.maxRows, 0, int(INT32_MAX))
   533  	c.rowPrefetch = props.GetInt(RowPrefetchKey, c.rowPrefetch, 0, int(INT32_MAX))
   534  	c.bufPrefetch = props.GetInt(BufPrefetchKey, c.bufPrefetch, int(Dm_build_66), int(Dm_build_67))
   535  	c.lobMode = props.GetInt(LobModeKey, c.lobMode, 1, 2)
   536  	c.stmtPoolMaxSize = props.GetInt(StmtPoolSizeKey, c.stmtPoolMaxSize, 0, int(INT32_MAX))
   537  	c.ignoreCase = props.GetBool(IgnoreCaseKey, c.ignoreCase)
   538  	c.alwayseAllowCommit = props.GetBool(AlwayseAllowCommitKey, c.alwayseAllowCommit)
   539  	c.batchType = props.GetInt(BatchTypeKey, c.batchType, 1, 2)
   540  	c.isBdtaRS = props.GetBool(IsBdtaRSKey, c.isBdtaRS)
   541  
   542  	c.callBatchNot = props.GetBool(CallBatchNotKey, c.callBatchNot)
   543  	c.sslFilesPath = props.GetTrimString(SslFilesPathKey, c.sslFilesPath)
   544  	c.sslCertPath = props.GetTrimString(SslCertPathKey, c.sslCertPath)
   545  	if c.sslCertPath == "" && c.sslFilesPath != "" {
   546  		c.sslCertPath = filepath.Join(c.sslFilesPath, "client-cert.pem")
   547  	}
   548  	c.sslKeyPath = props.GetTrimString(SslKeyPathKey, c.sslKeyPath)
   549  	if c.sslKeyPath == "" && c.sslFilesPath != "" {
   550  		c.sslKeyPath = filepath.Join(c.sslKeyPath, "client-key.pem")
   551  	}
   552  
   553  	c.kerberosLoginConfPath = props.GetTrimString(KerberosLoginConfPathKey, c.kerberosLoginConfPath)
   554  
   555  	c.uKeyName = props.GetTrimString(UKeyNameKey, c.uKeyName)
   556  	c.uKeyPin = props.GetTrimString(UKeyPinKey, c.uKeyPin)
   557  
   558  	if b := props.GetBool(ColumnNameUpperCaseKey, false); b {
   559  		c.columnNameCase = COLUMN_NAME_UPPDER_CASE
   560  	} else {
   561  		c.columnNameCase = 0
   562  	}
   563  
   564  	c.svcConfPath = props.GetString("confPath", "")
   565  
   566  	v := props.GetTrimString(ColumnNameCaseKey, "")
   567  	if util.StringUtil.EqualsIgnoreCase(v, "upper") {
   568  		c.columnNameCase = COLUMN_NAME_UPPDER_CASE
   569  	} else if util.StringUtil.EqualsIgnoreCase(v, "lower") {
   570  		c.columnNameCase = COLUMN_NAME_LOWER_CASE
   571  	}
   572  
   573  	c.schema = props.GetTrimString(SchemaKey, c.schema)
   574  
   575  	c.logLevel = ParseLogLevel(props)
   576  	LogLevel = c.logLevel
   577  	c.logDir = util.StringUtil.FormatDir(props.GetTrimString(LogDirKey, LogDirDef))
   578  	LogDir = c.logDir
   579  	c.logBufferSize = props.GetInt(LogBufferSizeKey, LogBufferSizeDef, 1, int(INT32_MAX))
   580  	LogBufferSize = c.logBufferSize
   581  	c.logFlushFreq = props.GetInt(LogFlushFreqKey, LogFlushFreqDef, 1, int(INT32_MAX))
   582  	LogFlushFreq = c.logFlushFreq
   583  	c.logFlushQueueSize = props.GetInt(LogFlusherQueueSizeKey, LogFlushQueueSizeDef, 1, int(INT32_MAX))
   584  	LogFlushQueueSize = c.logFlushQueueSize
   585  
   586  	c.statEnable = props.GetBool(StatEnableKey, StatEnableDef)
   587  	StatEnable = c.statEnable
   588  	c.statDir = util.StringUtil.FormatDir(props.GetTrimString(StatDirKey, StatDirDef))
   589  	StatDir = c.statDir
   590  	c.statFlushFreq = props.GetInt(StatFlushFreqKey, StatFlushFreqDef, 1, int(INT32_MAX))
   591  	StatFlushFreq = c.statFlushFreq
   592  	c.statHighFreqSqlCount = props.GetInt(StatHighFreqSqlCountKey, StatHighFreqSqlCountDef, 0, 1000)
   593  	StatHighFreqSqlCount = c.statHighFreqSqlCount
   594  	c.statSlowSqlCount = props.GetInt(StatSlowSqlCountKey, StatSlowSqlCountDef, 0, 1000)
   595  	StatSlowSqlCount = c.statSlowSqlCount
   596  	c.statSqlMaxCount = props.GetInt(StatSqlMaxCountKey, StatSqlMaxCountDef, 0, 100000)
   597  	StatSqlMaxCount = c.statSqlMaxCount
   598  	c.parseStatSqlRemoveMode(props)
   599  	return nil
   600  }
   601  
   602  func (c *DmConnector) parseOsAuthType(props *Properties) error {
   603  	value := props.GetString(OsAuthTypeKey, "")
   604  	if value != "" && !util.StringUtil.IsDigit(value) {
   605  		if util.StringUtil.EqualsIgnoreCase(value, "ON") {
   606  			c.osAuthType = Dm_build_64
   607  		} else if util.StringUtil.EqualsIgnoreCase(value, "SYSDBA") {
   608  			c.osAuthType = Dm_build_60
   609  		} else if util.StringUtil.EqualsIgnoreCase(value, "SYSAUDITOR") {
   610  			c.osAuthType = Dm_build_62
   611  		} else if util.StringUtil.EqualsIgnoreCase(value, "SYSSSO") {
   612  			c.osAuthType = Dm_build_61
   613  		} else if util.StringUtil.EqualsIgnoreCase(value, "AUTO") {
   614  			c.osAuthType = Dm_build_63
   615  		} else if util.StringUtil.EqualsIgnoreCase(value, "OFF") {
   616  			c.osAuthType = Dm_build_59
   617  		}
   618  	} else {
   619  		c.osAuthType = byte(props.GetInt(OsAuthTypeKey, int(c.osAuthType), 0, 4))
   620  	}
   621  	if c.user == "" && c.osAuthType == Dm_build_59 {
   622  		c.user = "SYSDBA"
   623  	} else if c.osAuthType != Dm_build_59 && c.user != "" {
   624  		ECGO_OSAUTH_ERROR.throw()
   625  	} else if c.osAuthType != Dm_build_59 {
   626  		c.user = os.Getenv("user")
   627  		c.password = ""
   628  	}
   629  	return nil
   630  }
   631  
   632  func (c *DmConnector) parseCompatibleMode(props *Properties) {
   633  	value := props.GetString(CompatibleModeKey, "")
   634  	if value != "" && !util.StringUtil.IsDigit(value) {
   635  		if util.StringUtil.EqualsIgnoreCase(value, "oracle") {
   636  			c.compatibleMode = COMPATIBLE_MODE_ORACLE
   637  		} else if util.StringUtil.EqualsIgnoreCase(value, "mysql") {
   638  			c.compatibleMode = COMPATIBLE_MODE_MYSQL
   639  		}
   640  	} else {
   641  		c.compatibleMode = props.GetInt(CompatibleModeKey, c.compatibleMode, 0, 2)
   642  	}
   643  }
   644  
   645  func (c *DmConnector) parseStatSqlRemoveMode(props *Properties) {
   646  	value := props.GetString(StatSqlRemoveModeKey, "")
   647  	if value != "" && !util.StringUtil.IsDigit(value) {
   648  		if util.StringUtil.EqualsIgnoreCase("oldest", value) || util.StringUtil.EqualsIgnoreCase("eldest", value) {
   649  			c.statSqlRemoveMode = STAT_SQL_REMOVE_OLDEST
   650  		} else if util.StringUtil.EqualsIgnoreCase("latest", value) {
   651  			c.statSqlRemoveMode = STAT_SQL_REMOVE_LATEST
   652  		}
   653  	} else {
   654  		c.statSqlRemoveMode = props.GetInt(StatSqlRemoveModeKey, StatSqlRemoveModeDef, 1, 2)
   655  	}
   656  }
   657  
   658  func (c *DmConnector) parseDSN(dsn string) (*Properties, string, error) {
   659  	dsn = AddressRemap(dsn)
   660  
   661  	var dsnProps = NewProperties()
   662  	url, err := url.Parse(dsn)
   663  	if err != nil {
   664  		return nil, "", err
   665  	}
   666  	if url.Scheme != "dm" {
   667  		return nil, "", DSN_INVALID_SCHEMA
   668  	}
   669  
   670  	if url.User != nil {
   671  		c.user = url.User.Username()
   672  		c.password, _ = url.User.Password()
   673  	}
   674  
   675  	q := url.Query()
   676  	for k := range q {
   677  		dsnProps.Set(k, q.Get(k))
   678  	}
   679  
   680  	return dsnProps, url.Host, nil
   681  }
   682  
   683  func (c *DmConnector) BuildDSN() string {
   684  	var buf bytes.Buffer
   685  
   686  	buf.WriteString("dm://")
   687  
   688  	if len(c.user) > 0 {
   689  		buf.WriteString(url.QueryEscape(c.user))
   690  		if len(c.password) > 0 {
   691  			buf.WriteByte(':')
   692  			buf.WriteString(url.QueryEscape(c.password))
   693  		}
   694  		buf.WriteByte('@')
   695  	}
   696  
   697  	if len(c.host) > 0 {
   698  		buf.WriteString(c.host)
   699  		if c.port > 0 {
   700  			buf.WriteByte(':')
   701  			buf.WriteString(strconv.Itoa(c.port))
   702  		}
   703  	}
   704  
   705  	hasParam := false
   706  	if c.connectTimeout > 0 {
   707  		if hasParam {
   708  			buf.WriteString("&timeout=")
   709  		} else {
   710  			buf.WriteString("?timeout=")
   711  			hasParam = true
   712  		}
   713  		buf.WriteString(strconv.Itoa(c.connectTimeout))
   714  	}
   715  	return buf.String()
   716  }
   717  
   718  func (c *DmConnector) mergeConfigs(dsn string) error {
   719  	props, host, err := c.parseDSN(dsn)
   720  	if err != nil {
   721  		return err
   722  	}
   723  
   724  	driverInit(props.GetString("svcConfPath", ""))
   725  
   726  	if group, ok := ServerGroupMap[strings.ToLower(host)]; ok {
   727  		c.group = group
   728  	} else {
   729  		host, port, err := net.SplitHostPort(host)
   730  		if err != nil || net.ParseIP(host) == nil {
   731  			c.host = hostDef
   732  		} else {
   733  			c.host = host
   734  		}
   735  		c.port, err = strconv.Atoi(port)
   736  		if err != nil {
   737  			c.port = portDef
   738  		}
   739  	}
   740  
   741  	UserRemap(props)
   742  
   743  	if c.group != nil && len(c.group.ServerList) > 1 {
   744  		props.SetDiffProperties(c.group.Props)
   745  
   746  		if props.GetBool(RwSeparateKey, false) {
   747  			props.Set(LoginModeKey, strconv.Itoa(LOGIN_MODE_PRIMARY))
   748  			props.Set(LoginStatusKey, strconv.Itoa(SERVER_STATUS_OPEN))
   749  		}
   750  	} else if c.group != nil {
   751  		props.Set("host", c.group.ServerList[0].host)
   752  		props.Set("port", strconv.Itoa(c.group.ServerList[0].port))
   753  	}
   754  	props.SetDiffProperties(GlobalProperties)
   755  
   756  	err = c.setAttributes(props)
   757  	if err != nil {
   758  		return err
   759  	}
   760  
   761  	return nil
   762  }
   763  
   764  func (c *DmConnector) Connect(ctx context.Context) (driver.Conn, error) {
   765  	return c.filterChain.reset().DmConnectorConnect(c, ctx)
   766  }
   767  
   768  func (c *DmConnector) Driver() driver.Driver {
   769  	return c.filterChain.reset().DmConnectorDriver(c)
   770  }
   771  
   772  func (c *DmConnector) connect(ctx context.Context) (*DmConnection, error) {
   773  	if c.group != nil && len(c.group.ServerList) > 1 {
   774  		return c.group.connect(c)
   775  	} else {
   776  		return c.connectSingle(ctx)
   777  	}
   778  }
   779  
   780  func (c *DmConnector) driver() *DmDriver {
   781  	return c.dmDriver
   782  }
   783  
   784  func (c *DmConnector) connectSingle(ctx context.Context) (*DmConnection, error) {
   785  	var err error
   786  	var dc *DmConnection
   787  	if c.reConnection == nil {
   788  		dc = &DmConnection{
   789  			closech: make(chan struct{}),
   790  		}
   791  		dc.dmConnector = c
   792  		dc.autoCommit = c.autoCommit
   793  		dc.createFilterChain(c, nil)
   794  
   795  		dc.objId = -1
   796  		dc.init()
   797  
   798  		dc.startWatcher()
   799  		if err = dc.watchCancel(ctx); err != nil {
   800  			return nil, err
   801  		}
   802  		defer dc.finish()
   803  	} else {
   804  		dc = c.reConnection
   805  		dc.reset()
   806  	}
   807  
   808  	dc.Access, err = dm_build_1296(dc)
   809  	if err != nil {
   810  		return nil, err
   811  	}
   812  
   813  	if err = dc.Access.dm_build_1337(); err != nil {
   814  
   815  		if !dc.closed.IsSet() {
   816  			close(dc.closech)
   817  			if dc.Access != nil {
   818  				dc.Access.Close()
   819  			}
   820  			dc.closed.Set(true)
   821  		}
   822  		return nil, err
   823  	}
   824  
   825  	if c.schema != "" {
   826  		_, err = dc.exec("set schema "+c.schema, nil)
   827  		if err != nil {
   828  			return nil, err
   829  		}
   830  	}
   831  
   832  	return dc, nil
   833  }