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