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