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 }