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