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

     1  /*
     2   * Copyright (c) 2000-2018, 达梦数据库有限公司.
     3   * All rights reserved.
     4   */
     5  package dmr
     6  
     7  import (
     8  	"bytes"
     9  	"context"
    10  	"database/sql/driver"
    11  	"fmt"
    12  	"net"
    13  	"net/url"
    14  	"os"
    15  	"path/filepath"
    16  	"regexp"
    17  	"runtime"
    18  	"strconv"
    19  	"strings"
    20  	"unicode/utf8"
    21  
    22  	"github.com/wanlay/gorm-dm8/dmr/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  	ClusterKey               = "cluster"
    53  	LanguageKey              = "language"
    54  	DbAliveCheckFreqKey      = "dbAliveCheckFreq"
    55  	RwStandbyRecoverTimeKey  = "rwStandbyRecoverTime"
    56  	LogLevelKey              = "logLevel"
    57  	LogDirKey                = "logDir"
    58  	LogBufferPoolSizeKey     = "logBufferPoolSize"
    59  	LogBufferSizeKey         = "logBufferSize"
    60  	LogFlusherQueueSizeKey   = "logFlusherQueueSize"
    61  	LogFlushFreqKey          = "logFlushFreq"
    62  	StatEnableKey            = "statEnable"
    63  	StatDirKey               = "statDir"
    64  	StatFlushFreqKey         = "statFlushFreq"
    65  	StatHighFreqSqlCountKey  = "statHighFreqSqlCount"
    66  	StatSlowSqlCountKey      = "statSlowSqlCount"
    67  	StatSqlMaxCountKey       = "statSqlMaxCount"
    68  	StatSqlRemoveModeKey     = "statSqlRemoveMode"
    69  	AddressRemapKey          = "addressRemap"
    70  	UserRemapKey             = "userRemap"
    71  	ConnectTimeoutKey        = "connectTimeout"
    72  	LoginCertificateKey      = "loginCertificate"
    73  	UrlKey                   = "url"
    74  	HostKey                  = "host"
    75  	PortKey                  = "port"
    76  	UserKey                  = "user"
    77  	PasswordKey              = "password"
    78  	RwStandbyKey             = "rwStandby"
    79  	IsCompressKey            = "isCompress"
    80  	RwHAKey                  = "rwHA"
    81  	RwIgnoreSqlKey           = "rwIgnoreSql"
    82  	AppNameKey               = "appName"
    83  	OsNameKey                = "osName"
    84  	MppLocalKey              = "mppLocal"
    85  	SocketTimeoutKey         = "socketTimeout"
    86  	SessionTimeoutKey        = "sessionTimeout"
    87  	ContinueBatchOnErrorKey  = "continueBatchOnError"
    88  	BatchAllowMaxErrorsKey   = "batchAllowMaxErrors"
    89  	EscapeProcessKey         = "escapeProcess"
    90  	AutoCommitKey            = "autoCommit"
    91  	MaxRowsKey               = "maxRows"
    92  	RowPrefetchKey           = "rowPrefetch"
    93  	BufPrefetchKey           = "bufPrefetch"
    94  	LobModeKey               = "LobMode"
    95  	StmtPoolSizeKey          = "StmtPoolSize"
    96  	IgnoreCaseKey            = "ignoreCase"
    97  	AlwayseAllowCommitKey    = "AlwayseAllowCommit"
    98  	BatchTypeKey             = "batchType"
    99  	BatchNotOnCallKey        = "batchNotOnCall"
   100  	IsBdtaRSKey              = "isBdtaRS"
   101  	ClobAsStringKey          = "clobAsString"
   102  	SslCertPathKey           = "sslCertPath"
   103  	SslKeyPathKey            = "sslKeyPath"
   104  	SslFilesPathKey          = "sslFilesPath"
   105  	KerberosLoginConfPathKey = "kerberosLoginConfPath"
   106  	UKeyNameKey              = "uKeyName"
   107  	UKeyPinKey               = "uKeyPin"
   108  	ColumnNameUpperCaseKey   = "columnNameUpperCase"
   109  	ColumnNameCaseKey        = "columnNameCase"
   110  	DatabaseProductNameKey   = "databaseProductName"
   111  	OsAuthTypeKey            = "osAuthType"
   112  	SchemaKey                = "schema"
   113  
   114  	TIME_ZONE_DEFAULT int16 = 480
   115  
   116  	DO_SWITCH_OFF             int32 = 0
   117  	DO_SWITCH_WHEN_CONN_ERROR int32 = 1
   118  	DO_SWITCH_WHEN_EP_RECOVER int32 = 2
   119  
   120  	CLUSTER_TYPE_NORMAL int32 = 0
   121  	CLUSTER_TYPE_RW     int32 = 1
   122  	CLUSTER_TYPE_DW     int32 = 2
   123  	CLUSTER_TYPE_DSC    int32 = 3
   124  	CLUSTER_TYPE_MPP    int32 = 4
   125  
   126  	EP_STATUS_OK    int32 = 1
   127  	EP_STATUS_ERROR int32 = 2
   128  
   129  	LOGIN_MODE_PRIMARY_FIRST int32 = 0
   130  
   131  	LOGIN_MODE_PRIMARY_ONLY int32 = 1
   132  
   133  	LOGIN_MODE_STANDBY_ONLY int32 = 2
   134  
   135  	LOGIN_MODE_STANDBY_FIRST int32 = 3
   136  
   137  	LOGIN_MODE_NORMAL_FIRST int32 = 4
   138  
   139  	SERVER_MODE_NORMAL int32 = 0
   140  
   141  	SERVER_MODE_PRIMARY int32 = 1
   142  
   143  	SERVER_MODE_STANDBY int32 = 2
   144  
   145  	SERVER_STATUS_MOUNT int32 = 3
   146  
   147  	SERVER_STATUS_OPEN int32 = 4
   148  
   149  	SERVER_STATUS_SUSPEND int32 = 5
   150  
   151  	COMPATIBLE_MODE_ORACLE int = 1
   152  
   153  	COMPATIBLE_MODE_MYSQL int = 2
   154  
   155  	LANGUAGE_CN int = 0
   156  
   157  	LANGUAGE_EN int = 1
   158  
   159  	COLUMN_NAME_NATURAL_CASE = 0
   160  
   161  	COLUMN_NAME_UPPER_CASE = 1
   162  
   163  	COLUMN_NAME_LOWER_CASE = 2
   164  
   165  	compressDef   = Dm_build_681
   166  	compressIDDef = Dm_build_682
   167  
   168  	charCodeDef = ""
   169  
   170  	enRsCacheDef = false
   171  
   172  	rsCacheSizeDef = 20
   173  
   174  	rsRefreshFreqDef = 10
   175  
   176  	loginModeDef = LOGIN_MODE_NORMAL_FIRST
   177  
   178  	loginStatusDef = 0
   179  
   180  	loginEncryptDef = true
   181  
   182  	loginCertificateDef = ""
   183  
   184  	dec2DoubleDef = false
   185  
   186  	rwHADef = false
   187  
   188  	rwStandbyDef = false
   189  
   190  	rwSeparateDef = false
   191  
   192  	rwPercentDef = 25
   193  
   194  	rwAutoDistributeDef = true
   195  
   196  	rwStandbyRecoverTimeDef = 1000
   197  
   198  	cipherPathDef = ""
   199  
   200  	urlDef = ""
   201  
   202  	userDef = "SYSDBA"
   203  
   204  	passwordDef = "SYSDBA"
   205  
   206  	hostDef = "localhost"
   207  
   208  	portDef = DEFAULT_PORT
   209  
   210  	appNameDef = ""
   211  
   212  	mppLocalDef = false
   213  
   214  	socketTimeoutDef = 0
   215  
   216  	connectTimeoutDef = 5000
   217  
   218  	sessionTimeoutDef = 0
   219  
   220  	osAuthTypeDef = Dm_build_664
   221  
   222  	continueBatchOnErrorDef = false
   223  
   224  	escapeProcessDef = false
   225  
   226  	autoCommitDef = true
   227  
   228  	maxRowsDef = 0
   229  
   230  	rowPrefetchDef = Dm_build_665
   231  
   232  	bufPrefetchDef = 0
   233  
   234  	lobModeDef = 1
   235  
   236  	stmtPoolMaxSizeDef = 15
   237  
   238  	ignoreCaseDef = true
   239  
   240  	alwayseAllowCommitDef = true
   241  
   242  	isBdtaRSDef = false
   243  
   244  	kerberosLoginConfPathDef = ""
   245  
   246  	uKeyNameDef = ""
   247  
   248  	uKeyPinDef = ""
   249  
   250  	databaseProductNameDef = ""
   251  
   252  	caseSensitiveDef = true
   253  
   254  	compatibleModeDef = 0
   255  
   256  	localTimezoneDef = TIME_ZONE_DEFAULT
   257  )
   258  
   259  type DmConnector struct {
   260  	filterable
   261  
   262  	dmDriver *DmDriver
   263  
   264  	compress int
   265  
   266  	compressID int8
   267  
   268  	newClientType bool
   269  
   270  	charCode string
   271  
   272  	enRsCache bool
   273  
   274  	rsCacheSize int
   275  
   276  	rsRefreshFreq int
   277  
   278  	loginMode int32
   279  
   280  	loginStatus int
   281  
   282  	loginDscCtrl bool
   283  
   284  	switchTimes int32
   285  
   286  	switchInterval int
   287  
   288  	epSelector int32
   289  
   290  	keyWords []string
   291  
   292  	loginEncrypt bool
   293  
   294  	loginCertificate string
   295  
   296  	dec2Double bool
   297  
   298  	rwHA bool
   299  
   300  	rwStandby bool
   301  
   302  	rwSeparate bool
   303  
   304  	rwPercent int32
   305  
   306  	rwAutoDistribute bool
   307  
   308  	rwStandbyRecoverTime int
   309  
   310  	rwIgnoreSql bool
   311  
   312  	doSwitch int32
   313  
   314  	cluster int32
   315  
   316  	cipherPath string
   317  
   318  	url string
   319  
   320  	user string
   321  
   322  	password string
   323  
   324  	host string
   325  
   326  	group *epGroup
   327  
   328  	port int32
   329  
   330  	appName string
   331  
   332  	osName string
   333  
   334  	mppLocal bool
   335  
   336  	socketTimeout int
   337  
   338  	connectTimeout int
   339  
   340  	sessionTimeout int
   341  
   342  	osAuthType byte
   343  
   344  	continueBatchOnError bool
   345  
   346  	batchAllowMaxErrors int32
   347  
   348  	escapeProcess bool
   349  
   350  	autoCommit bool
   351  
   352  	maxRows int
   353  
   354  	rowPrefetch int
   355  
   356  	bufPrefetch int
   357  
   358  	lobMode int
   359  
   360  	stmtPoolMaxSize int
   361  
   362  	ignoreCase bool
   363  
   364  	alwayseAllowCommit bool
   365  
   366  	batchType int
   367  
   368  	batchNotOnCall bool
   369  
   370  	isBdtaRS bool
   371  
   372  	sslCertPath string
   373  
   374  	sslKeyPath string
   375  
   376  	sslFilesPath string
   377  
   378  	kerberosLoginConfPath string
   379  
   380  	uKeyName string
   381  
   382  	uKeyPin string
   383  
   384  	svcConfPath string
   385  
   386  	columnNameCase int
   387  
   388  	caseSensitive bool
   389  
   390  	compatibleMode int
   391  
   392  	localTimezone int16
   393  
   394  	schema string
   395  
   396  	reConnection *DmConnection
   397  
   398  	logLevel int
   399  
   400  	logDir string
   401  
   402  	logFlushFreq int
   403  
   404  	logFlushQueueSize int
   405  
   406  	logBufferSize int
   407  
   408  	statEnable bool
   409  
   410  	statDir string
   411  
   412  	statFlushFreq int
   413  
   414  	statSlowSqlCount int
   415  
   416  	statHighFreqSqlCount int
   417  
   418  	statSqlMaxCount int
   419  
   420  	statSqlRemoveMode int
   421  }
   422  
   423  func (c *DmConnector) init() *DmConnector {
   424  	c.compress = compressDef
   425  	c.compressID = compressIDDef
   426  	c.charCode = charCodeDef
   427  	c.enRsCache = enRsCacheDef
   428  	c.rsCacheSize = rsCacheSizeDef
   429  	c.rsRefreshFreq = rsRefreshFreqDef
   430  	c.loginMode = loginModeDef
   431  	c.loginStatus = loginStatusDef
   432  	c.loginDscCtrl = false
   433  	c.switchTimes = 1
   434  	c.switchInterval = 1000
   435  	c.epSelector = 0
   436  	c.keyWords = nil
   437  	c.loginEncrypt = loginEncryptDef
   438  	c.loginCertificate = loginCertificateDef
   439  	c.dec2Double = dec2DoubleDef
   440  	c.rwHA = rwHADef
   441  	c.rwStandby = rwStandbyDef
   442  	c.rwSeparate = rwSeparateDef
   443  	c.rwPercent = rwPercentDef
   444  	c.rwAutoDistribute = rwAutoDistributeDef
   445  	c.rwStandbyRecoverTime = rwStandbyRecoverTimeDef
   446  	c.rwIgnoreSql = false
   447  	c.doSwitch = DO_SWITCH_OFF
   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  	c.localTimezone = localTimezoneDef
   483  	c.idGenerator = dmConntorIDGenerator
   484  
   485  	c.logDir = LogDirDef
   486  	c.logFlushFreq = LogFlushFreqDef
   487  	c.logFlushQueueSize = LogFlushQueueSizeDef
   488  	c.logBufferSize = LogBufferSizeDef
   489  	c.statEnable = StatEnableDef
   490  	c.statDir = StatDirDef
   491  	c.statFlushFreq = StatFlushFreqDef
   492  	c.statSlowSqlCount = StatSlowSqlCountDef
   493  	c.statHighFreqSqlCount = StatHighFreqSqlCountDef
   494  	c.statSqlMaxCount = StatSqlMaxCountDef
   495  	c.statSqlRemoveMode = StatSqlRemoveModeDef
   496  	return c
   497  }
   498  
   499  func (c *DmConnector) setAttributes(props *Properties) error {
   500  	if props == nil || props.Len() == 0 {
   501  		return nil
   502  	}
   503  
   504  	c.url = props.GetTrimString(UrlKey, c.url)
   505  	c.host = props.GetTrimString(HostKey, c.host)
   506  	c.port = int32(props.GetInt(PortKey, int(c.port), 0, 65535))
   507  	c.user = props.GetString(UserKey, c.user)
   508  	c.password = props.GetString(PasswordKey, c.password)
   509  	c.rwStandby = props.GetBool(RwStandbyKey, c.rwStandby)
   510  
   511  	if b := props.GetBool(IsCompressKey, false); b {
   512  		c.compress = Dm_build_680
   513  	}
   514  
   515  	c.compress = props.GetInt(CompressKey, c.compress, 0, 2)
   516  	c.compressID = int8(props.GetInt(CompressIdKey, int(c.compressID), 0, 1))
   517  	c.enRsCache = props.GetBool(EnRsCacheKey, c.enRsCache)
   518  	c.localTimezone = int16(props.GetInt(TimeZoneKey, int(c.localTimezone), -720, 720))
   519  	c.rsCacheSize = props.GetInt(RsCacheSizeKey, c.rsCacheSize, 0, int(INT32_MAX))
   520  	c.rsRefreshFreq = props.GetInt(RsRefreshFreqKey, c.rsRefreshFreq, 0, int(INT32_MAX))
   521  	c.loginMode = int32(props.GetInt(LoginModeKey, int(c.loginMode), 0, 4))
   522  	c.loginStatus = props.GetInt(LoginStatusKey, c.loginStatus, 0, int(INT32_MAX))
   523  	c.loginDscCtrl = props.GetBool(LoginDscCtrlKey, c.loginDscCtrl)
   524  	c.switchTimes = int32(props.GetInt(SwitchTimesKey, int(c.switchTimes), 0, int(INT32_MAX)))
   525  	c.switchInterval = props.GetInt(SwitchIntervalKey, c.switchInterval, 0, int(INT32_MAX))
   526  	c.epSelector = int32(props.GetInt(EpSelectorKey, int(c.epSelector), 0, 1))
   527  	c.loginEncrypt = props.GetBool(LoginEncryptKey, c.loginEncrypt)
   528  	c.loginCertificate = props.GetTrimString(LoginCertificateKey, c.loginCertificate)
   529  	c.dec2Double = props.GetBool(Dec2DoubleKey, c.dec2Double)
   530  
   531  	c.rwSeparate = props.GetBool(RwSeparateKey, c.rwSeparate)
   532  	c.rwAutoDistribute = props.GetBool(RwAutoDistributeKey, c.rwAutoDistribute)
   533  	c.rwPercent = int32(props.GetInt(RwPercentKey, int(c.rwPercent), 0, 100))
   534  	c.rwHA = props.GetBool(RwHAKey, c.rwHA)
   535  	c.rwStandbyRecoverTime = props.GetInt(RwStandbyRecoverTimeKey, c.rwStandbyRecoverTime, 0, int(INT32_MAX))
   536  	c.rwIgnoreSql = props.GetBool(RwIgnoreSqlKey, c.rwIgnoreSql)
   537  	c.doSwitch = int32(props.GetInt(DoSwitchKey, int(c.doSwitch), 0, 2))
   538  	c.parseCluster(props)
   539  	c.cipherPath = props.GetTrimString(CipherPathKey, c.cipherPath)
   540  
   541  	if props.GetBool(CompatibleOraKey, false) {
   542  		c.compatibleMode = int(COMPATIBLE_MODE_ORACLE)
   543  	}
   544  	c.parseCompatibleMode(props)
   545  	c.keyWords = props.GetStringArray(KeywordsKey, c.keyWords)
   546  
   547  	c.appName = props.GetTrimString(AppNameKey, c.appName)
   548  	c.osName = props.GetTrimString(OsNameKey, c.osName)
   549  	c.mppLocal = props.GetBool(MppLocalKey, c.mppLocal)
   550  	c.socketTimeout = props.GetInt(SocketTimeoutKey, c.socketTimeout, 0, int(INT32_MAX))
   551  	c.connectTimeout = props.GetInt(ConnectTimeoutKey, c.connectTimeout, 0, int(INT32_MAX))
   552  	c.sessionTimeout = props.GetInt(SessionTimeoutKey, c.sessionTimeout, 0, int(INT32_MAX))
   553  
   554  	err := c.parseOsAuthType(props)
   555  	if err != nil {
   556  		return err
   557  	}
   558  	c.continueBatchOnError = props.GetBool(ContinueBatchOnErrorKey, c.continueBatchOnError)
   559  	c.batchAllowMaxErrors = int32(props.GetInt(BatchAllowMaxErrorsKey, int(c.batchAllowMaxErrors), 0, int(INT32_MAX)))
   560  	c.escapeProcess = props.GetBool(EscapeProcessKey, c.escapeProcess)
   561  	c.autoCommit = props.GetBool(AutoCommitKey, c.autoCommit)
   562  	c.maxRows = props.GetInt(MaxRowsKey, c.maxRows, 0, int(INT32_MAX))
   563  	c.rowPrefetch = props.GetInt(RowPrefetchKey, c.rowPrefetch, 0, int(INT32_MAX))
   564  	c.bufPrefetch = props.GetInt(BufPrefetchKey, c.bufPrefetch, int(Dm_build_666), int(Dm_build_667))
   565  	c.lobMode = props.GetInt(LobModeKey, c.lobMode, 1, 2)
   566  	c.stmtPoolMaxSize = props.GetInt(StmtPoolSizeKey, c.stmtPoolMaxSize, 0, int(INT32_MAX))
   567  	c.ignoreCase = props.GetBool(IgnoreCaseKey, c.ignoreCase)
   568  	c.alwayseAllowCommit = props.GetBool(AlwayseAllowCommitKey, c.alwayseAllowCommit)
   569  	c.batchType = props.GetInt(BatchTypeKey, c.batchType, 1, 2)
   570  	c.batchNotOnCall = props.GetBool(BatchNotOnCallKey, c.batchNotOnCall)
   571  	c.isBdtaRS = props.GetBool(IsBdtaRSKey, c.isBdtaRS)
   572  	c.sslFilesPath = props.GetTrimString(SslFilesPathKey, c.sslFilesPath)
   573  	c.sslCertPath = props.GetTrimString(SslCertPathKey, c.sslCertPath)
   574  	if c.sslCertPath == "" && c.sslFilesPath != "" {
   575  		c.sslCertPath = filepath.Join(c.sslFilesPath, "client-cert.pem")
   576  	}
   577  	c.sslKeyPath = props.GetTrimString(SslKeyPathKey, c.sslKeyPath)
   578  	if c.sslKeyPath == "" && c.sslFilesPath != "" {
   579  		c.sslKeyPath = filepath.Join(c.sslKeyPath, "client-key.pem")
   580  	}
   581  
   582  	c.kerberosLoginConfPath = props.GetTrimString(KerberosLoginConfPathKey, c.kerberosLoginConfPath)
   583  
   584  	c.uKeyName = props.GetTrimString(UKeyNameKey, c.uKeyName)
   585  	c.uKeyPin = props.GetTrimString(UKeyPinKey, c.uKeyPin)
   586  
   587  	c.svcConfPath = props.GetString("confPath", "")
   588  
   589  	if props.GetBool(ColumnNameUpperCaseKey, false) {
   590  		c.columnNameCase = COLUMN_NAME_UPPER_CASE
   591  	}
   592  
   593  	v := props.GetTrimString(ColumnNameCaseKey, "")
   594  	if util.StringUtil.EqualsIgnoreCase(v, "upper") {
   595  		c.columnNameCase = COLUMN_NAME_UPPER_CASE
   596  	} else if util.StringUtil.EqualsIgnoreCase(v, "lower") {
   597  		c.columnNameCase = COLUMN_NAME_LOWER_CASE
   598  	}
   599  
   600  	c.schema = props.GetTrimString(SchemaKey, c.schema)
   601  
   602  	c.logLevel = ParseLogLevel(props)
   603  	LogLevel = c.logLevel
   604  	c.logDir = util.StringUtil.FormatDir(props.GetTrimString(LogDirKey, LogDirDef))
   605  	LogDir = c.logDir
   606  	c.logBufferSize = props.GetInt(LogBufferSizeKey, LogBufferSizeDef, 1, int(INT32_MAX))
   607  	LogBufferSize = c.logBufferSize
   608  	c.logFlushFreq = props.GetInt(LogFlushFreqKey, LogFlushFreqDef, 1, int(INT32_MAX))
   609  	LogFlushFreq = c.logFlushFreq
   610  	c.logFlushQueueSize = props.GetInt(LogFlusherQueueSizeKey, LogFlushQueueSizeDef, 1, int(INT32_MAX))
   611  	LogFlushQueueSize = c.logFlushQueueSize
   612  
   613  	c.statEnable = props.GetBool(StatEnableKey, StatEnableDef)
   614  	StatEnable = c.statEnable
   615  	c.statDir = util.StringUtil.FormatDir(props.GetTrimString(StatDirKey, StatDirDef))
   616  	StatDir = c.statDir
   617  	c.statFlushFreq = props.GetInt(StatFlushFreqKey, StatFlushFreqDef, 1, int(INT32_MAX))
   618  	StatFlushFreq = c.statFlushFreq
   619  	c.statHighFreqSqlCount = props.GetInt(StatHighFreqSqlCountKey, StatHighFreqSqlCountDef, 0, 1000)
   620  	StatHighFreqSqlCount = c.statHighFreqSqlCount
   621  	c.statSlowSqlCount = props.GetInt(StatSlowSqlCountKey, StatSlowSqlCountDef, 0, 1000)
   622  	StatSlowSqlCount = c.statSlowSqlCount
   623  	c.statSqlMaxCount = props.GetInt(StatSqlMaxCountKey, StatSqlMaxCountDef, 0, 100000)
   624  	StatSqlMaxCount = c.statSqlMaxCount
   625  	c.parseStatSqlRemoveMode(props)
   626  	return nil
   627  }
   628  
   629  func (c *DmConnector) parseOsAuthType(props *Properties) error {
   630  	value := props.GetString(OsAuthTypeKey, "")
   631  	if value != "" && !util.StringUtil.IsDigit(value) {
   632  		if util.StringUtil.EqualsIgnoreCase(value, "ON") {
   633  			c.osAuthType = Dm_build_664
   634  		} else if util.StringUtil.EqualsIgnoreCase(value, "SYSDBA") {
   635  			c.osAuthType = Dm_build_660
   636  		} else if util.StringUtil.EqualsIgnoreCase(value, "SYSAUDITOR") {
   637  			c.osAuthType = Dm_build_662
   638  		} else if util.StringUtil.EqualsIgnoreCase(value, "SYSSSO") {
   639  			c.osAuthType = Dm_build_661
   640  		} else if util.StringUtil.EqualsIgnoreCase(value, "AUTO") {
   641  			c.osAuthType = Dm_build_663
   642  		} else if util.StringUtil.EqualsIgnoreCase(value, "OFF") {
   643  			c.osAuthType = Dm_build_659
   644  		}
   645  	} else {
   646  		c.osAuthType = byte(props.GetInt(OsAuthTypeKey, int(c.osAuthType), 0, 4))
   647  	}
   648  	if c.user == "" && c.osAuthType == Dm_build_659 {
   649  		c.user = "SYSDBA"
   650  	} else if c.osAuthType != Dm_build_659 && c.user != "" {
   651  		return ECGO_OSAUTH_ERROR.throw()
   652  	} else if c.osAuthType != Dm_build_659 {
   653  		c.user = os.Getenv("user")
   654  		c.password = ""
   655  	}
   656  	return nil
   657  }
   658  
   659  func (c *DmConnector) parseCompatibleMode(props *Properties) {
   660  	value := props.GetString(CompatibleModeKey, "")
   661  	if value != "" && !util.StringUtil.IsDigit(value) {
   662  		if util.StringUtil.EqualsIgnoreCase(value, "oracle") {
   663  			c.compatibleMode = COMPATIBLE_MODE_ORACLE
   664  		} else if util.StringUtil.EqualsIgnoreCase(value, "mysql") {
   665  			c.compatibleMode = COMPATIBLE_MODE_MYSQL
   666  		}
   667  	} else {
   668  		c.compatibleMode = props.GetInt(CompatibleModeKey, c.compatibleMode, 0, 2)
   669  	}
   670  }
   671  
   672  func (c *DmConnector) parseStatSqlRemoveMode(props *Properties) {
   673  	value := props.GetString(StatSqlRemoveModeKey, "")
   674  	if value != "" && !util.StringUtil.IsDigit(value) {
   675  		if util.StringUtil.EqualsIgnoreCase("oldest", value) || util.StringUtil.EqualsIgnoreCase("eldest", value) {
   676  			c.statSqlRemoveMode = STAT_SQL_REMOVE_OLDEST
   677  		} else if util.StringUtil.EqualsIgnoreCase("latest", value) {
   678  			c.statSqlRemoveMode = STAT_SQL_REMOVE_LATEST
   679  		}
   680  	} else {
   681  		c.statSqlRemoveMode = props.GetInt(StatSqlRemoveModeKey, StatSqlRemoveModeDef, 1, 2)
   682  	}
   683  }
   684  
   685  func (c *DmConnector) parseCluster(props *Properties) {
   686  	value := props.GetTrimString(ClusterKey, "")
   687  	if util.StringUtil.EqualsIgnoreCase(value, "DSC") {
   688  		c.cluster = CLUSTER_TYPE_DSC
   689  	} else if util.StringUtil.EqualsIgnoreCase(value, "RW") {
   690  		c.cluster = CLUSTER_TYPE_RW
   691  	} else if util.StringUtil.EqualsIgnoreCase(value, "DW") {
   692  		c.cluster = CLUSTER_TYPE_DW
   693  	} else if util.StringUtil.EqualsIgnoreCase(value, "MPP") {
   694  		c.cluster = CLUSTER_TYPE_MPP
   695  	} else {
   696  		c.cluster = CLUSTER_TYPE_NORMAL
   697  	}
   698  }
   699  
   700  func (c *DmConnector) parseDSN(dsn string) (*Properties, string, error) {
   701  	var dsnProps = NewProperties()
   702  	url, err := url.Parse(dsn)
   703  	if err != nil {
   704  		return nil, "", err
   705  	}
   706  	if url.Scheme != "dm" {
   707  		return nil, "", DSN_INVALID_SCHEMA
   708  	}
   709  
   710  	if url.User != nil {
   711  		c.user = url.User.Username()
   712  		c.password, _ = url.User.Password()
   713  	}
   714  
   715  	q := url.Query()
   716  	for k := range q {
   717  		dsnProps.Set(k, q.Get(k))
   718  	}
   719  
   720  	return dsnProps, url.Host, nil
   721  }
   722  
   723  func (c *DmConnector) BuildDSN() string {
   724  	var buf bytes.Buffer
   725  
   726  	buf.WriteString("dm://")
   727  
   728  	if len(c.user) > 0 {
   729  		buf.WriteString(url.QueryEscape(c.user))
   730  		if len(c.password) > 0 {
   731  			buf.WriteByte(':')
   732  			buf.WriteString(url.QueryEscape(c.password))
   733  		}
   734  		buf.WriteByte('@')
   735  	}
   736  
   737  	if len(c.host) > 0 {
   738  		buf.WriteString(c.host)
   739  		if c.port > 0 {
   740  			buf.WriteByte(':')
   741  			buf.WriteString(strconv.Itoa(int(c.port)))
   742  		}
   743  	}
   744  
   745  	hasParam := false
   746  	if c.connectTimeout > 0 {
   747  		if hasParam {
   748  			buf.WriteString("&timeout=")
   749  		} else {
   750  			buf.WriteString("?timeout=")
   751  			hasParam = true
   752  		}
   753  		buf.WriteString(strconv.Itoa(c.connectTimeout))
   754  	}
   755  	return buf.String()
   756  }
   757  
   758  func (c *DmConnector) mergeConfigs(dsn string) error {
   759  	props, host, err := c.parseDSN(dsn)
   760  	if err != nil {
   761  		return err
   762  	}
   763  
   764  	driverInit(props.GetString("svcConfPath", ""))
   765  
   766  	addressRemapStr := props.GetTrimString(AddressRemapKey, "")
   767  	userRemapStr := props.GetTrimString(UserRemapKey, "")
   768  	if addressRemapStr == "" {
   769  		addressRemapStr = GlobalProperties.GetTrimString(AddressRemapKey, "")
   770  	}
   771  	if userRemapStr == "" {
   772  		userRemapStr = GlobalProperties.GetTrimString(UserRemapKey, "")
   773  	}
   774  
   775  	host = c.remap(host, addressRemapStr)
   776  
   777  	c.user = c.remap(c.user, userRemapStr)
   778  
   779  	if group, ok := ServerGroupMap[strings.ToLower(host)]; ok {
   780  		c.group = group
   781  	} else {
   782  		host, port, err := net.SplitHostPort(host)
   783  		errDomain := checkDomain(host)
   784  		isDomain := errDomain == nil
   785  		if err != nil || (net.ParseIP(host) == nil && !isDomain) {
   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  	return c.filterChain.reset().DmConnectorConnect(c, ctx)
   834  }
   835  
   836  func (c *DmConnector) Driver() driver.Driver {
   837  	return c.filterChain.reset().DmConnectorDriver(c)
   838  }
   839  
   840  func (c *DmConnector) connect(ctx context.Context) (*DmConnection, error) {
   841  	if c.group != nil && len(c.group.epList) > 0 {
   842  		return c.group.connect(c)
   843  	} else {
   844  		return c.connectSingle(ctx)
   845  	}
   846  }
   847  
   848  func (c *DmConnector) driver() *DmDriver {
   849  	return c.dmDriver
   850  }
   851  
   852  func (c *DmConnector) connectSingle(ctx context.Context) (*DmConnection, error) {
   853  	var err error
   854  	var dc *DmConnection
   855  	if c.reConnection == nil {
   856  		dc = &DmConnection{
   857  			closech: make(chan struct{}),
   858  		}
   859  		dc.dmConnector = c
   860  		dc.autoCommit = c.autoCommit
   861  		dc.createFilterChain(c, nil)
   862  
   863  		dc.objId = -1
   864  		dc.init()
   865  	} else {
   866  		dc = c.reConnection
   867  		dc.reset()
   868  	}
   869  
   870  	dc.Access, err = dm_build_344(dc)
   871  	if err != nil {
   872  		return nil, err
   873  	}
   874  
   875  	dc.startWatcher()
   876  	if err = dc.watchCancel(ctx); err != nil {
   877  		return nil, err
   878  	}
   879  	defer dc.finish()
   880  
   881  	if err = dc.Access.dm_build_385(); err != nil {
   882  
   883  		if !dc.closed.IsSet() {
   884  			close(dc.closech)
   885  			if dc.Access != nil {
   886  				dc.Access.Close()
   887  			}
   888  			dc.closed.Set(true)
   889  		}
   890  		return nil, err
   891  	}
   892  
   893  	if c.schema != "" {
   894  		_, err = dc.exec("set schema "+c.schema, nil)
   895  		if err != nil {
   896  			return nil, err
   897  		}
   898  	}
   899  
   900  	return dc, nil
   901  }
   902  
   903  func checkDomain(name string) error {
   904  	switch {
   905  	case len(name) == 0:
   906  		return nil // an empty domain name will result in a cookie without a domain restriction
   907  	case len(name) > 255:
   908  		return fmt.Errorf("cookie domain: name length is %d, can't exceed 255", len(name))
   909  	}
   910  	var l int
   911  	for i := 0; i < len(name); i++ {
   912  		b := name[i]
   913  		if b == '.' {
   914  			// check domain labels validity
   915  			switch {
   916  			case i == l:
   917  				return fmt.Errorf("cookie domain: invalid character '%c' at offset %d: label can't begin with a period", b, i)
   918  			case i-l > 63:
   919  				return fmt.Errorf("cookie domain: byte length of label '%s' is %d, can't exceed 63", name[l:i], i-l)
   920  			case name[l] == '-':
   921  				return fmt.Errorf("cookie domain: label '%s' at offset %d begins with a hyphen", name[l:i], l)
   922  			case name[i-1] == '-':
   923  				return fmt.Errorf("cookie domain: label '%s' at offset %d ends with a hyphen", name[l:i], l)
   924  			}
   925  			l = i + 1
   926  			continue
   927  		}
   928  		// test label character validity, note: tests are ordered by decreasing validity frequency
   929  		if !(b >= 'a' && b <= 'z' || b >= '0' && b <= '9' || b == '-' || b >= 'A' && b <= 'Z') {
   930  			// show the printable unicode character starting at byte offset i
   931  			c, _ := utf8.DecodeRuneInString(name[i:])
   932  			if c == utf8.RuneError {
   933  				return fmt.Errorf("cookie domain: invalid rune at offset %d", i)
   934  			}
   935  			return fmt.Errorf("cookie domain: invalid character '%c' at offset %d", c, i)
   936  		}
   937  	}
   938  	// check top level domain validity
   939  	switch {
   940  	case l == len(name):
   941  		return fmt.Errorf("cookie domain: missing top level domain, domain can't end with a period")
   942  	case len(name)-l > 63:
   943  		return fmt.Errorf("cookie domain: byte length of top level domain '%s' is %d, can't exceed 63", name[l:], len(name)-l)
   944  	case name[l] == '-':
   945  		return fmt.Errorf("cookie domain: top level domain '%s' at offset %d begins with a hyphen", name[l:], l)
   946  	case name[len(name)-1] == '-':
   947  		return fmt.Errorf("cookie domain: top level domain '%s' at offset %d ends with a hyphen", name[l:], l)
   948  	case name[l] >= '0' && name[l] <= '9':
   949  		return fmt.Errorf("cookie domain: top level domain '%s' at offset %d begins with a digit", name[l:], l)
   950  	}
   951  	return nil
   952  }