gitee.com/runner.mei/dm@v0.0.0-20220207044607-a9ba0dc20bf7/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 20 "gitee.com/runner.mei/dm/util" 21 ) 22 23 const ( 24 TimeZoneKey = "timeZone" 25 EnRsCacheKey = "enRsCache" 26 RsCacheSizeKey = "rsCacheSize" 27 RsRefreshFreqKey = "rsRefreshFreq" 28 LoginPrimary = "loginPrimary" 29 LoginModeKey = "loginMode" 30 LoginStatusKey = "loginStatus" 31 LoginDscCtrlKey = "loginDscCtrl" 32 SwitchTimesKey = "switchTimes" 33 SwitchIntervalKey = "switchInterval" 34 EpSelectorKey = "epSelector" 35 PrimaryKey = "primaryKey" 36 KeywordsKey = "keywords" 37 CompressKey = "compress" 38 CompressIdKey = "compressId" 39 LoginEncryptKey = "loginEncrypt" 40 CommunicationEncryptKey = "communicationEncrypt" 41 DirectKey = "direct" 42 Dec2DoubleKey = "dec2double" 43 RwSeparateKey = "rwSeparate" 44 RwPercentKey = "rwPercent" 45 RwAutoDistributeKey = "rwAutoDistribute" 46 CompatibleModeKey = "compatibleMode" 47 CompatibleOraKey = "comOra" 48 CipherPathKey = "cipherPath" 49 DoSwitchKey = "doSwitch" 50 ClusterKey = "cluster" 51 LanguageKey = "language" 52 DbAliveCheckFreqKey = "dbAliveCheckFreq" 53 RwStandbyRecoverTimeKey = "rwStandbyRecoverTime" 54 LogLevelKey = "logLevel" 55 LogDirKey = "logDir" 56 LogBufferPoolSizeKey = "logBufferPoolSize" 57 LogBufferSizeKey = "logBufferSize" 58 LogFlusherQueueSizeKey = "logFlusherQueueSize" 59 LogFlushFreqKey = "logFlushFreq" 60 StatEnableKey = "statEnable" 61 StatDirKey = "statDir" 62 StatFlushFreqKey = "statFlushFreq" 63 StatHighFreqSqlCountKey = "statHighFreqSqlCount" 64 StatSlowSqlCountKey = "statSlowSqlCount" 65 StatSqlMaxCountKey = "statSqlMaxCount" 66 StatSqlRemoveModeKey = "statSqlRemoveMode" 67 AddressRemapKey = "addressRemap" 68 UserRemapKey = "userRemap" 69 ConnectTimeoutKey = "connectTimeout" 70 LoginCertificateKey = "loginCertificate" 71 UrlKey = "url" 72 HostKey = "host" 73 PortKey = "port" 74 UserKey = "user" 75 PasswordKey = "password" 76 RwStandbyKey = "rwStandby" 77 IsCompressKey = "isCompress" 78 RwHAKey = "rwHA" 79 RwIgnoreSqlKey = "rwIgnoreSql" 80 AppNameKey = "appName" 81 OsNameKey = "osName" 82 MppLocalKey = "mppLocal" 83 SocketTimeoutKey = "socketTimeout" 84 SessionTimeoutKey = "sessionTimeout" 85 ContinueBatchOnErrorKey = "continueBatchOnError" 86 BatchAllowMaxErrorsKey = "batchAllowMaxErrors" 87 EscapeProcessKey = "escapeProcess" 88 AutoCommitKey = "autoCommit" 89 MaxRowsKey = "maxRows" 90 RowPrefetchKey = "rowPrefetch" 91 BufPrefetchKey = "bufPrefetch" 92 LobModeKey = "LobMode" 93 StmtPoolSizeKey = "StmtPoolSize" 94 IgnoreCaseKey = "ignoreCase" 95 AlwayseAllowCommitKey = "AlwayseAllowCommit" 96 BatchTypeKey = "batchType" 97 BatchNotOnCallKey = "batchNotOnCall" 98 IsBdtaRSKey = "isBdtaRS" 99 ClobAsStringKey = "clobAsString" 100 SslCertPathKey = "sslCertPath" 101 SslKeyPathKey = "sslKeyPath" 102 SslFilesPathKey = "sslFilesPath" 103 KerberosLoginConfPathKey = "kerberosLoginConfPath" 104 UKeyNameKey = "uKeyName" 105 UKeyPinKey = "uKeyPin" 106 ColumnNameUpperCaseKey = "columnNameUpperCase" 107 ColumnNameCaseKey = "columnNameCase" 108 DatabaseProductNameKey = "databaseProductName" 109 OsAuthTypeKey = "osAuthType" 110 SchemaKey = "schema" 111 NoConvertToHexKey = "noConvertToHex" 112 113 TIME_ZONE_DEFAULT int16 = 480 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_84 165 compressIDDef = Dm_build_85 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_67 220 221 continueBatchOnErrorDef = false 222 223 escapeProcessDef = false 224 225 autoCommitDef = true 226 227 maxRowsDef = 0 228 229 rowPrefetchDef = Dm_build_68 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 localTimezoneDef = TIME_ZONE_DEFAULT 256 ) 257 258 type DmConnector struct { 259 filterable 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 cluster int32 314 315 cipherPath string 316 317 url string 318 319 user string 320 321 password string 322 323 host string 324 325 group *epGroup 326 327 port int32 328 329 appName string 330 331 osName string 332 333 mppLocal bool 334 335 socketTimeout int 336 337 connectTimeout int 338 339 sessionTimeout int 340 341 osAuthType byte 342 343 continueBatchOnError bool 344 345 batchAllowMaxErrors int32 346 347 escapeProcess bool 348 349 autoCommit bool 350 351 maxRows int 352 353 rowPrefetch int 354 355 bufPrefetch int 356 357 lobMode int 358 359 stmtPoolMaxSize int 360 361 ignoreCase bool 362 363 alwayseAllowCommit bool 364 365 batchType int 366 367 batchNotOnCall bool 368 369 isBdtaRS bool 370 371 sslCertPath string 372 373 sslKeyPath string 374 375 sslFilesPath string 376 377 kerberosLoginConfPath string 378 379 uKeyName string 380 381 uKeyPin string 382 383 svcConfPath string 384 385 columnNameCase int 386 387 caseSensitive bool 388 389 compatibleMode int 390 391 localTimezone int16 392 393 schema string 394 395 reConnection *DmConnection 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 noConvertToHex bool 422 } 423 424 func (c *DmConnector) init() *DmConnector { 425 c.compress = compressDef 426 c.compressID = compressIDDef 427 c.charCode = charCodeDef 428 c.enRsCache = enRsCacheDef 429 c.rsCacheSize = rsCacheSizeDef 430 c.rsRefreshFreq = rsRefreshFreqDef 431 c.loginMode = loginModeDef 432 c.loginStatus = loginStatusDef 433 c.loginDscCtrl = false 434 c.switchTimes = 1 435 c.switchInterval = 1000 436 c.epSelector = 0 437 c.keyWords = nil 438 c.loginEncrypt = loginEncryptDef 439 c.loginCertificate = loginCertificateDef 440 c.dec2Double = dec2DoubleDef 441 c.rwHA = rwHADef 442 c.rwStandby = rwStandbyDef 443 c.rwSeparate = rwSeparateDef 444 c.rwPercent = rwPercentDef 445 c.rwAutoDistribute = rwAutoDistributeDef 446 c.rwStandbyRecoverTime = rwStandbyRecoverTimeDef 447 c.rwIgnoreSql = false 448 c.doSwitch = DO_SWITCH_OFF 449 c.cluster = CLUSTER_TYPE_NORMAL 450 c.cipherPath = cipherPathDef 451 c.url = urlDef 452 c.user = userDef 453 c.password = passwordDef 454 c.host = hostDef 455 c.port = portDef 456 c.appName = appNameDef 457 c.osName = runtime.GOOS 458 c.mppLocal = mppLocalDef 459 c.socketTimeout = socketTimeoutDef 460 c.connectTimeout = connectTimeoutDef 461 c.sessionTimeout = sessionTimeoutDef 462 c.osAuthType = osAuthTypeDef 463 c.continueBatchOnError = continueBatchOnErrorDef 464 c.batchAllowMaxErrors = 0 465 c.escapeProcess = escapeProcessDef 466 c.autoCommit = autoCommitDef 467 c.maxRows = maxRowsDef 468 c.rowPrefetch = rowPrefetchDef 469 c.bufPrefetch = bufPrefetchDef 470 c.lobMode = lobModeDef 471 c.stmtPoolMaxSize = stmtPoolMaxSizeDef 472 c.ignoreCase = ignoreCaseDef 473 c.alwayseAllowCommit = alwayseAllowCommitDef 474 c.batchType = 1 475 c.batchNotOnCall = false 476 c.isBdtaRS = isBdtaRSDef 477 c.kerberosLoginConfPath = kerberosLoginConfPathDef 478 c.uKeyName = uKeyNameDef 479 c.uKeyPin = uKeyPinDef 480 c.columnNameCase = COLUMN_NAME_NATURAL_CASE 481 c.caseSensitive = caseSensitiveDef 482 c.compatibleMode = compatibleModeDef 483 c.localTimezone = localTimezoneDef 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_83 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.parseCluster(props) 540 c.cipherPath = props.GetTrimString(CipherPathKey, c.cipherPath) 541 542 if props.GetBool(CompatibleOraKey, false) { 543 c.compatibleMode = int(COMPATIBLE_MODE_ORACLE) 544 } 545 c.parseCompatibleMode(props) 546 c.keyWords = props.GetStringArray(KeywordsKey, c.keyWords) 547 548 c.appName = props.GetTrimString(AppNameKey, c.appName) 549 c.osName = props.GetTrimString(OsNameKey, c.osName) 550 c.mppLocal = props.GetBool(MppLocalKey, c.mppLocal) 551 c.socketTimeout = props.GetInt(SocketTimeoutKey, c.socketTimeout, 0, int(INT32_MAX)) 552 c.connectTimeout = props.GetInt(ConnectTimeoutKey, c.connectTimeout, 0, int(INT32_MAX)) 553 c.sessionTimeout = props.GetInt(SessionTimeoutKey, c.sessionTimeout, 0, int(INT32_MAX)) 554 555 err := c.parseOsAuthType(props) 556 if err != nil { 557 return err 558 } 559 c.continueBatchOnError = props.GetBool(ContinueBatchOnErrorKey, c.continueBatchOnError) 560 c.batchAllowMaxErrors = int32(props.GetInt(BatchAllowMaxErrorsKey, int(c.batchAllowMaxErrors), 0, int(INT32_MAX))) 561 c.escapeProcess = props.GetBool(EscapeProcessKey, c.escapeProcess) 562 c.autoCommit = props.GetBool(AutoCommitKey, c.autoCommit) 563 c.maxRows = props.GetInt(MaxRowsKey, c.maxRows, 0, int(INT32_MAX)) 564 c.rowPrefetch = props.GetInt(RowPrefetchKey, c.rowPrefetch, 0, int(INT32_MAX)) 565 c.bufPrefetch = props.GetInt(BufPrefetchKey, c.bufPrefetch, int(Dm_build_69), int(Dm_build_70)) 566 c.lobMode = props.GetInt(LobModeKey, c.lobMode, 1, 2) 567 c.stmtPoolMaxSize = props.GetInt(StmtPoolSizeKey, c.stmtPoolMaxSize, 0, int(INT32_MAX)) 568 c.ignoreCase = props.GetBool(IgnoreCaseKey, c.ignoreCase) 569 c.alwayseAllowCommit = props.GetBool(AlwayseAllowCommitKey, c.alwayseAllowCommit) 570 c.batchType = props.GetInt(BatchTypeKey, c.batchType, 1, 2) 571 c.batchNotOnCall = props.GetBool(BatchNotOnCallKey, c.batchNotOnCall) 572 c.isBdtaRS = props.GetBool(IsBdtaRSKey, c.isBdtaRS) 573 c.sslFilesPath = props.GetTrimString(SslFilesPathKey, c.sslFilesPath) 574 c.sslCertPath = props.GetTrimString(SslCertPathKey, c.sslCertPath) 575 if c.sslCertPath == "" && c.sslFilesPath != "" { 576 c.sslCertPath = filepath.Join(c.sslFilesPath, "client-cert.pem") 577 } 578 c.sslKeyPath = props.GetTrimString(SslKeyPathKey, c.sslKeyPath) 579 if c.sslKeyPath == "" && c.sslFilesPath != "" { 580 c.sslKeyPath = filepath.Join(c.sslKeyPath, "client-key.pem") 581 } 582 583 c.kerberosLoginConfPath = props.GetTrimString(KerberosLoginConfPathKey, c.kerberosLoginConfPath) 584 585 c.uKeyName = props.GetTrimString(UKeyNameKey, c.uKeyName) 586 c.uKeyPin = props.GetTrimString(UKeyPinKey, c.uKeyPin) 587 588 c.svcConfPath = props.GetString("confPath", "") 589 590 if props.GetBool(ColumnNameUpperCaseKey, false) { 591 c.columnNameCase = COLUMN_NAME_UPPER_CASE 592 } 593 594 v := props.GetTrimString(ColumnNameCaseKey, "") 595 if util.StringUtil.EqualsIgnoreCase(v, "upper") { 596 c.columnNameCase = COLUMN_NAME_UPPER_CASE 597 } else if util.StringUtil.EqualsIgnoreCase(v, "lower") { 598 c.columnNameCase = COLUMN_NAME_LOWER_CASE 599 } 600 601 c.schema = props.GetTrimString(SchemaKey, c.schema) 602 603 c.logLevel = ParseLogLevel(props) 604 LogLevel = c.logLevel 605 c.logDir = util.StringUtil.FormatDir(props.GetTrimString(LogDirKey, LogDirDef)) 606 LogDir = c.logDir 607 c.logBufferSize = props.GetInt(LogBufferSizeKey, LogBufferSizeDef, 1, int(INT32_MAX)) 608 LogBufferSize = c.logBufferSize 609 c.logFlushFreq = props.GetInt(LogFlushFreqKey, LogFlushFreqDef, 1, int(INT32_MAX)) 610 LogFlushFreq = c.logFlushFreq 611 c.logFlushQueueSize = props.GetInt(LogFlusherQueueSizeKey, LogFlushQueueSizeDef, 1, int(INT32_MAX)) 612 LogFlushQueueSize = c.logFlushQueueSize 613 614 c.statEnable = props.GetBool(StatEnableKey, StatEnableDef) 615 StatEnable = c.statEnable 616 c.statDir = util.StringUtil.FormatDir(props.GetTrimString(StatDirKey, StatDirDef)) 617 StatDir = c.statDir 618 c.statFlushFreq = props.GetInt(StatFlushFreqKey, StatFlushFreqDef, 1, int(INT32_MAX)) 619 StatFlushFreq = c.statFlushFreq 620 c.statHighFreqSqlCount = props.GetInt(StatHighFreqSqlCountKey, StatHighFreqSqlCountDef, 0, 1000) 621 StatHighFreqSqlCount = c.statHighFreqSqlCount 622 c.statSlowSqlCount = props.GetInt(StatSlowSqlCountKey, StatSlowSqlCountDef, 0, 1000) 623 StatSlowSqlCount = c.statSlowSqlCount 624 c.statSqlMaxCount = props.GetInt(StatSqlMaxCountKey, StatSqlMaxCountDef, 0, 100000) 625 StatSqlMaxCount = c.statSqlMaxCount 626 c.parseStatSqlRemoveMode(props) 627 628 c.noConvertToHex = props.GetBool(NoConvertToHexKey, false) 629 return nil 630 } 631 632 func (c *DmConnector) parseOsAuthType(props *Properties) error { 633 value := props.GetString(OsAuthTypeKey, "") 634 if value != "" && !util.StringUtil.IsDigit(value) { 635 if util.StringUtil.EqualsIgnoreCase(value, "ON") { 636 c.osAuthType = Dm_build_67 637 } else if util.StringUtil.EqualsIgnoreCase(value, "SYSDBA") { 638 c.osAuthType = Dm_build_63 639 } else if util.StringUtil.EqualsIgnoreCase(value, "SYSAUDITOR") { 640 c.osAuthType = Dm_build_65 641 } else if util.StringUtil.EqualsIgnoreCase(value, "SYSSSO") { 642 c.osAuthType = Dm_build_64 643 } else if util.StringUtil.EqualsIgnoreCase(value, "AUTO") { 644 c.osAuthType = Dm_build_66 645 } else if util.StringUtil.EqualsIgnoreCase(value, "OFF") { 646 c.osAuthType = Dm_build_62 647 } 648 } else { 649 c.osAuthType = byte(props.GetInt(OsAuthTypeKey, int(c.osAuthType), 0, 4)) 650 } 651 if c.user == "" && c.osAuthType == Dm_build_62 { 652 c.user = "SYSDBA" 653 } else if c.osAuthType != Dm_build_62 && c.user != "" { 654 return ECGO_OSAUTH_ERROR.throw() 655 } else if c.osAuthType != Dm_build_62 { 656 c.user = os.Getenv("user") 657 c.password = "" 658 } 659 return nil 660 } 661 662 func (c *DmConnector) parseCompatibleMode(props *Properties) { 663 value := props.GetString(CompatibleModeKey, "") 664 if value != "" && !util.StringUtil.IsDigit(value) { 665 if util.StringUtil.EqualsIgnoreCase(value, "oracle") { 666 c.compatibleMode = COMPATIBLE_MODE_ORACLE 667 } else if util.StringUtil.EqualsIgnoreCase(value, "mysql") { 668 c.compatibleMode = COMPATIBLE_MODE_MYSQL 669 } 670 } else { 671 c.compatibleMode = props.GetInt(CompatibleModeKey, c.compatibleMode, 0, 2) 672 } 673 } 674 675 func (c *DmConnector) parseStatSqlRemoveMode(props *Properties) { 676 value := props.GetString(StatSqlRemoveModeKey, "") 677 if value != "" && !util.StringUtil.IsDigit(value) { 678 if util.StringUtil.EqualsIgnoreCase("oldest", value) || util.StringUtil.EqualsIgnoreCase("eldest", value) { 679 c.statSqlRemoveMode = STAT_SQL_REMOVE_OLDEST 680 } else if util.StringUtil.EqualsIgnoreCase("latest", value) { 681 c.statSqlRemoveMode = STAT_SQL_REMOVE_LATEST 682 } 683 } else { 684 c.statSqlRemoveMode = props.GetInt(StatSqlRemoveModeKey, StatSqlRemoveModeDef, 1, 2) 685 } 686 } 687 688 func (c *DmConnector) parseCluster(props *Properties) { 689 value := props.GetTrimString(ClusterKey, "") 690 if util.StringUtil.EqualsIgnoreCase(value, "DSC") { 691 c.cluster = CLUSTER_TYPE_DSC 692 } else if util.StringUtil.EqualsIgnoreCase(value, "RW") { 693 c.cluster = CLUSTER_TYPE_RW 694 } else if util.StringUtil.EqualsIgnoreCase(value, "DW") { 695 c.cluster = CLUSTER_TYPE_DW 696 } else if util.StringUtil.EqualsIgnoreCase(value, "MPP") { 697 c.cluster = CLUSTER_TYPE_MPP 698 } else { 699 c.cluster = CLUSTER_TYPE_NORMAL 700 } 701 } 702 703 func (c *DmConnector) parseDSN(dsn string) (*Properties, string, error) { 704 var dsnProps = NewProperties() 705 url, err := url.Parse(dsn) 706 if err != nil { 707 return nil, "", err 708 } 709 if url.Scheme != "dm" { 710 return nil, "", DSN_INVALID_SCHEMA 711 } 712 713 if url.User != nil { 714 c.user = url.User.Username() 715 c.password, _ = url.User.Password() 716 } 717 718 q := url.Query() 719 for k := range q { 720 dsnProps.Set(k, q.Get(k)) 721 } 722 723 return dsnProps, url.Host, nil 724 } 725 726 func (c *DmConnector) BuildDSN() string { 727 var buf bytes.Buffer 728 729 buf.WriteString("dm://") 730 731 if len(c.user) > 0 { 732 buf.WriteString(url.QueryEscape(c.user)) 733 if len(c.password) > 0 { 734 buf.WriteByte(':') 735 buf.WriteString(url.QueryEscape(c.password)) 736 } 737 buf.WriteByte('@') 738 } 739 740 if len(c.host) > 0 { 741 buf.WriteString(c.host) 742 if c.port > 0 { 743 buf.WriteByte(':') 744 buf.WriteString(strconv.Itoa(int(c.port))) 745 } 746 } 747 748 hasParam := false 749 if c.connectTimeout > 0 { 750 if hasParam { 751 buf.WriteString("&timeout=") 752 } else { 753 buf.WriteString("?timeout=") 754 hasParam = true 755 } 756 buf.WriteString(strconv.Itoa(c.connectTimeout)) 757 } 758 return buf.String() 759 } 760 761 func (c *DmConnector) mergeConfigs(dsn string) error { 762 props, host, err := c.parseDSN(dsn) 763 if err != nil { 764 return err 765 } 766 767 driverInit(props.GetString("svcConfPath", "")) 768 769 addressRemapStr := props.GetTrimString(AddressRemapKey, "") 770 userRemapStr := props.GetTrimString(UserRemapKey, "") 771 if addressRemapStr == "" { 772 addressRemapStr = GlobalProperties.GetTrimString(AddressRemapKey, "") 773 } 774 if userRemapStr == "" { 775 userRemapStr = GlobalProperties.GetTrimString(UserRemapKey, "") 776 } 777 778 host = c.remap(host, addressRemapStr) 779 780 c.user = c.remap(c.user, userRemapStr) 781 782 if group, ok := ServerGroupMap[strings.ToLower(host)]; ok { 783 c.group = group 784 } else { 785 host, port, err := net.SplitHostPort(host) 786 if err != nil || net.ParseIP(host) == nil { 787 c.host = hostDef 788 } else { 789 c.host = host 790 } 791 tmpPort, err := strconv.Atoi(port) 792 if err != nil { 793 c.port = portDef 794 } else { 795 c.port = int32(tmpPort) 796 } 797 798 c.group = newEPGroup(c.host+":"+strconv.Itoa(int(c.port)), []*ep{newEP(c.host, c.port)}) 799 } 800 801 props.SetDiffProperties(c.group.props) 802 803 props.SetDiffProperties(GlobalProperties) 804 805 if props.GetBool(RwSeparateKey, false) { 806 props.SetIfNotExist(LoginModeKey, strconv.Itoa(int(LOGIN_MODE_PRIMARY_ONLY))) 807 props.SetIfNotExist(LoginStatusKey, strconv.Itoa(int(SERVER_STATUS_OPEN))) 808 809 props.SetIfNotExist(DoSwitchKey, "true") 810 } 811 812 if err = c.setAttributes(props); err != nil { 813 return err 814 } 815 return nil 816 } 817 818 func (c *DmConnector) remap(origin string, cfgStr string) string { 819 if cfgStr == "" || origin == "" { 820 return origin 821 } 822 823 maps := regexp.MustCompile("\\(.*?,.*?\\)").FindAllString(cfgStr, -1) 824 for _, kvStr := range maps { 825 kv := strings.Split(strings.TrimSpace(kvStr[1:len(kvStr)-1]), ",") 826 if util.StringUtil.Equals(strings.TrimSpace(kv[0]), origin) { 827 return strings.TrimSpace(kv[1]) 828 } 829 } 830 return origin 831 } 832 833 func (c *DmConnector) Connect(ctx context.Context) (driver.Conn, error) { 834 return c.filterChain.reset().DmConnectorConnect(c, ctx) 835 } 836 837 func (c *DmConnector) Driver() driver.Driver { 838 return c.filterChain.reset().DmConnectorDriver(c) 839 } 840 841 func (c *DmConnector) connect(ctx context.Context) (*DmConnection, error) { 842 if c.group != nil && len(c.group.epList) > 0 { 843 return c.group.connect(c) 844 } else { 845 return c.connectSingle(ctx) 846 } 847 } 848 849 func (c *DmConnector) driver() *DmDriver { 850 return c.dmDriver 851 } 852 853 func (c *DmConnector) connectSingle(ctx context.Context) (*DmConnection, error) { 854 var err error 855 var dc *DmConnection 856 if c.reConnection == nil { 857 dc = &DmConnection{ 858 closech: make(chan struct{}), 859 } 860 dc.dmConnector = c 861 dc.autoCommit = c.autoCommit 862 dc.createFilterChain(c, nil) 863 864 dc.objId = -1 865 dc.init() 866 } else { 867 dc = c.reConnection 868 dc.reset() 869 } 870 871 dc.Access, err = dm_build_1324(dc) 872 if err != nil { 873 return nil, err 874 } 875 876 dc.startWatcher() 877 if err = dc.watchCancel(ctx); err != nil { 878 return nil, err 879 } 880 defer dc.finish() 881 882 if err = dc.Access.dm_build_1365(); err != nil { 883 884 if !dc.closed.IsSet() { 885 close(dc.closech) 886 if dc.Access != nil { 887 dc.Access.Close() 888 } 889 dc.closed.Set(true) 890 } 891 return nil, err 892 } 893 894 if c.schema != "" { 895 _, err = dc.exec("set schema "+c.schema, nil) 896 if err != nil { 897 return nil, err 898 } 899 } 900 901 return dc, nil 902 }