n.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923
  1. /*
  2. * Copyright (c) 2000-2018, 达梦数据库有限公司.
  3. * All rights reserved.
  4. */
  5. package dm
  6. import (
  7. "bytes"
  8. "context"
  9. "database/sql/driver"
  10. "net"
  11. "net/url"
  12. "os"
  13. "path/filepath"
  14. "regexp"
  15. "runtime"
  16. "strconv"
  17. "strings"
  18. "sync"
  19. "time"
  20. "gitee.com/chunanyong/dm/util"
  21. )
  22. const (
  23. TimeZoneKey = "timeZone"
  24. EnRsCacheKey = "enRsCache"
  25. RsCacheSizeKey = "rsCacheSize"
  26. RsRefreshFreqKey = "rsRefreshFreq"
  27. LoginPrimary = "loginPrimary"
  28. LoginModeKey = "loginMode"
  29. LoginStatusKey = "loginStatus"
  30. LoginDscCtrlKey = "loginDscCtrl"
  31. SwitchTimesKey = "switchTimes"
  32. SwitchIntervalKey = "switchInterval"
  33. EpSelectorKey = "epSelector"
  34. PrimaryKey = "primaryKey"
  35. KeywordsKey = "keywords"
  36. CompressKey = "compress"
  37. CompressIdKey = "compressId"
  38. LoginEncryptKey = "loginEncrypt"
  39. CommunicationEncryptKey = "communicationEncrypt"
  40. DirectKey = "direct"
  41. Dec2DoubleKey = "dec2double"
  42. RwSeparateKey = "rwSeparate"
  43. RwPercentKey = "rwPercent"
  44. RwAutoDistributeKey = "rwAutoDistribute"
  45. CompatibleModeKey = "compatibleMode"
  46. CompatibleOraKey = "comOra"
  47. CipherPathKey = "cipherPath"
  48. DoSwitchKey = "doSwitch"
  49. DriverReconnectKey = "driverReconnect"
  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. DialNameKey = "dialName"
  77. RwStandbyKey = "rwStandby"
  78. IsCompressKey = "isCompress"
  79. RwHAKey = "rwHA"
  80. RwIgnoreSqlKey = "rwIgnoreSql"
  81. AppNameKey = "appName"
  82. OsNameKey = "osName"
  83. MppLocalKey = "mppLocal"
  84. SocketTimeoutKey = "socketTimeout"
  85. SessionTimeoutKey = "sessionTimeout"
  86. ContinueBatchOnErrorKey = "continueBatchOnError"
  87. BatchAllowMaxErrorsKey = "batchAllowMaxErrors"
  88. EscapeProcessKey = "escapeProcess"
  89. AutoCommitKey = "autoCommit"
  90. MaxRowsKey = "maxRows"
  91. RowPrefetchKey = "rowPrefetch"
  92. BufPrefetchKey = "bufPrefetch"
  93. LobModeKey = "LobMode"
  94. StmtPoolSizeKey = "StmtPoolSize"
  95. IgnoreCaseKey = "ignoreCase"
  96. AlwayseAllowCommitKey = "AlwayseAllowCommit"
  97. BatchTypeKey = "batchType"
  98. BatchNotOnCallKey = "batchNotOnCall"
  99. IsBdtaRSKey = "isBdtaRS"
  100. ClobAsStringKey = "clobAsString"
  101. SslCertPathKey = "sslCertPath"
  102. SslKeyPathKey = "sslKeyPath"
  103. SslFilesPathKey = "sslFilesPath"
  104. KerberosLoginConfPathKey = "kerberosLoginConfPath"
  105. UKeyNameKey = "uKeyName"
  106. UKeyPinKey = "uKeyPin"
  107. ColumnNameUpperCaseKey = "columnNameUpperCase"
  108. ColumnNameCaseKey = "columnNameCase"
  109. DatabaseProductNameKey = "databaseProductName"
  110. OsAuthTypeKey = "osAuthType"
  111. SchemaKey = "schema"
  112. DO_SWITCH_OFF int32 = 0
  113. DO_SWITCH_WHEN_CONN_ERROR int32 = 1
  114. DO_SWITCH_WHEN_EP_RECOVER int32 = 2
  115. CLUSTER_TYPE_NORMAL int32 = 0
  116. CLUSTER_TYPE_RW int32 = 1
  117. CLUSTER_TYPE_DW int32 = 2
  118. CLUSTER_TYPE_DSC int32 = 3
  119. CLUSTER_TYPE_MPP int32 = 4
  120. EP_STATUS_OK int32 = 1
  121. EP_STATUS_ERROR int32 = 2
  122. LOGIN_MODE_PRIMARY_FIRST int32 = 0
  123. LOGIN_MODE_PRIMARY_ONLY int32 = 1
  124. LOGIN_MODE_STANDBY_ONLY int32 = 2
  125. LOGIN_MODE_STANDBY_FIRST int32 = 3
  126. LOGIN_MODE_NORMAL_FIRST int32 = 4
  127. SERVER_MODE_NORMAL int32 = 0
  128. SERVER_MODE_PRIMARY int32 = 1
  129. SERVER_MODE_STANDBY int32 = 2
  130. SERVER_STATUS_MOUNT int32 = 3
  131. SERVER_STATUS_OPEN int32 = 4
  132. SERVER_STATUS_SUSPEND int32 = 5
  133. COMPATIBLE_MODE_ORACLE int = 1
  134. COMPATIBLE_MODE_MYSQL int = 2
  135. LANGUAGE_CN int = 0
  136. LANGUAGE_EN int = 1
  137. LANGUAGE_CNT_HK = 2
  138. COLUMN_NAME_NATURAL_CASE = 0
  139. COLUMN_NAME_UPPER_CASE = 1
  140. COLUMN_NAME_LOWER_CASE = 2
  141. compressDef = Dm_build_91
  142. compressIDDef = Dm_build_92
  143. charCodeDef = ""
  144. enRsCacheDef = false
  145. rsCacheSizeDef = 20
  146. rsRefreshFreqDef = 10
  147. loginModeDef = LOGIN_MODE_NORMAL_FIRST
  148. loginStatusDef = 0
  149. loginEncryptDef = true
  150. loginCertificateDef = ""
  151. dec2DoubleDef = false
  152. rwHADef = false
  153. rwStandbyDef = false
  154. rwSeparateDef = false
  155. rwPercentDef = 25
  156. rwAutoDistributeDef = true
  157. rwStandbyRecoverTimeDef = 1000
  158. cipherPathDef = ""
  159. urlDef = ""
  160. userDef = "SYSDBA"
  161. passwordDef = "SYSDBA"
  162. hostDef = "localhost"
  163. portDef = DEFAULT_PORT
  164. appNameDef = ""
  165. mppLocalDef = false
  166. socketTimeoutDef = 0
  167. connectTimeoutDef = 5000
  168. sessionTimeoutDef = 0
  169. osAuthTypeDef = Dm_build_74
  170. continueBatchOnErrorDef = false
  171. escapeProcessDef = false
  172. autoCommitDef = true
  173. maxRowsDef = 0
  174. rowPrefetchDef = Dm_build_75
  175. bufPrefetchDef = 0
  176. lobModeDef = 1
  177. stmtPoolMaxSizeDef = 15
  178. ignoreCaseDef = true
  179. alwayseAllowCommitDef = true
  180. isBdtaRSDef = false
  181. kerberosLoginConfPathDef = ""
  182. uKeyNameDef = ""
  183. uKeyPinDef = ""
  184. databaseProductNameDef = ""
  185. caseSensitiveDef = true
  186. compatibleModeDef = 0
  187. )
  188. type DmConnector struct {
  189. filterable
  190. mu sync.Mutex
  191. dmDriver *DmDriver
  192. compress int
  193. compressID int8
  194. newClientType bool
  195. charCode string
  196. enRsCache bool
  197. rsCacheSize int
  198. rsRefreshFreq int
  199. loginMode int32
  200. loginStatus int
  201. loginDscCtrl bool
  202. switchTimes int32
  203. switchInterval int
  204. epSelector int32
  205. keyWords []string
  206. loginEncrypt bool
  207. loginCertificate string
  208. dec2Double bool
  209. rwHA bool
  210. rwStandby bool
  211. rwSeparate bool
  212. rwPercent int32
  213. rwAutoDistribute bool
  214. rwStandbyRecoverTime int
  215. rwIgnoreSql bool
  216. doSwitch int32
  217. driverReconnect bool
  218. cluster int32
  219. cipherPath string
  220. url string
  221. user string
  222. password string
  223. dialName string
  224. host string
  225. group *epGroup
  226. port int32
  227. appName string
  228. osName string
  229. mppLocal bool
  230. socketTimeout int
  231. connectTimeout int
  232. sessionTimeout int
  233. osAuthType byte
  234. continueBatchOnError bool
  235. batchAllowMaxErrors int32
  236. escapeProcess bool
  237. autoCommit bool
  238. maxRows int
  239. rowPrefetch int
  240. bufPrefetch int
  241. lobMode int
  242. stmtPoolMaxSize int
  243. ignoreCase bool
  244. alwayseAllowCommit bool
  245. batchType int
  246. batchNotOnCall bool
  247. isBdtaRS bool
  248. sslCertPath string
  249. sslKeyPath string
  250. sslFilesPath string
  251. kerberosLoginConfPath string
  252. uKeyName string
  253. uKeyPin string
  254. svcConfPath string
  255. columnNameCase int
  256. caseSensitive bool
  257. compatibleMode int
  258. localTimezone int16
  259. schema string
  260. logLevel int
  261. logDir string
  262. logFlushFreq int
  263. logFlushQueueSize int
  264. logBufferSize int
  265. statEnable bool
  266. statDir string
  267. statFlushFreq int
  268. statSlowSqlCount int
  269. statHighFreqSqlCount int
  270. statSqlMaxCount int
  271. statSqlRemoveMode int
  272. }
  273. func (c *DmConnector) init() *DmConnector {
  274. c.compress = compressDef
  275. c.compressID = compressIDDef
  276. c.charCode = charCodeDef
  277. c.enRsCache = enRsCacheDef
  278. c.rsCacheSize = rsCacheSizeDef
  279. c.rsRefreshFreq = rsRefreshFreqDef
  280. c.loginMode = loginModeDef
  281. c.loginStatus = loginStatusDef
  282. c.loginDscCtrl = false
  283. c.switchTimes = 1
  284. c.switchInterval = 1000
  285. c.epSelector = 0
  286. c.keyWords = nil
  287. c.loginEncrypt = loginEncryptDef
  288. c.loginCertificate = loginCertificateDef
  289. c.dec2Double = dec2DoubleDef
  290. c.rwHA = rwHADef
  291. c.rwStandby = rwStandbyDef
  292. c.rwSeparate = rwSeparateDef
  293. c.rwPercent = rwPercentDef
  294. c.rwAutoDistribute = rwAutoDistributeDef
  295. c.rwStandbyRecoverTime = rwStandbyRecoverTimeDef
  296. c.rwIgnoreSql = false
  297. c.doSwitch = DO_SWITCH_WHEN_CONN_ERROR
  298. c.driverReconnect = false
  299. c.cluster = CLUSTER_TYPE_NORMAL
  300. c.cipherPath = cipherPathDef
  301. c.url = urlDef
  302. c.user = userDef
  303. c.password = passwordDef
  304. c.host = hostDef
  305. c.port = portDef
  306. c.appName = appNameDef
  307. c.osName = runtime.GOOS
  308. c.mppLocal = mppLocalDef
  309. c.socketTimeout = socketTimeoutDef
  310. c.connectTimeout = connectTimeoutDef
  311. c.sessionTimeout = sessionTimeoutDef
  312. c.osAuthType = osAuthTypeDef
  313. c.continueBatchOnError = continueBatchOnErrorDef
  314. c.batchAllowMaxErrors = 0
  315. c.escapeProcess = escapeProcessDef
  316. c.autoCommit = autoCommitDef
  317. c.maxRows = maxRowsDef
  318. c.rowPrefetch = rowPrefetchDef
  319. c.bufPrefetch = bufPrefetchDef
  320. c.lobMode = lobModeDef
  321. c.stmtPoolMaxSize = stmtPoolMaxSizeDef
  322. c.ignoreCase = ignoreCaseDef
  323. c.alwayseAllowCommit = alwayseAllowCommitDef
  324. c.batchType = 1
  325. c.batchNotOnCall = false
  326. c.isBdtaRS = isBdtaRSDef
  327. c.kerberosLoginConfPath = kerberosLoginConfPathDef
  328. c.uKeyName = uKeyNameDef
  329. c.uKeyPin = uKeyPinDef
  330. c.columnNameCase = COLUMN_NAME_NATURAL_CASE
  331. c.caseSensitive = caseSensitiveDef
  332. c.compatibleMode = compatibleModeDef
  333. _, tzs := time.Now().Zone()
  334. c.localTimezone = int16(tzs / 60)
  335. c.idGenerator = dmConntorIDGenerator
  336. c.logDir = LogDirDef
  337. c.logFlushFreq = LogFlushFreqDef
  338. c.logFlushQueueSize = LogFlushQueueSizeDef
  339. c.logBufferSize = LogBufferSizeDef
  340. c.statEnable = StatEnableDef
  341. c.statDir = StatDirDef
  342. c.statFlushFreq = StatFlushFreqDef
  343. c.statSlowSqlCount = StatSlowSqlCountDef
  344. c.statHighFreqSqlCount = StatHighFreqSqlCountDef
  345. c.statSqlMaxCount = StatSqlMaxCountDef
  346. c.statSqlRemoveMode = StatSqlRemoveModeDef
  347. return c
  348. }
  349. func (c *DmConnector) setAttributes(props *Properties) error {
  350. if props == nil || props.Len() == 0 {
  351. return nil
  352. }
  353. c.url = props.GetTrimString(UrlKey, c.url)
  354. c.host = props.GetTrimString(HostKey, c.host)
  355. c.port = int32(props.GetInt(PortKey, int(c.port), 0, 65535))
  356. c.user = props.GetString(UserKey, c.user)
  357. c.password = props.GetString(PasswordKey, c.password)
  358. c.dialName = props.GetString(DialNameKey, "")
  359. c.rwStandby = props.GetBool(RwStandbyKey, c.rwStandby)
  360. if b := props.GetBool(IsCompressKey, false); b {
  361. c.compress = Dm_build_90
  362. }
  363. c.compress = props.GetInt(CompressKey, c.compress, 0, 2)
  364. c.compressID = int8(props.GetInt(CompressIdKey, int(c.compressID), 0, 1))
  365. c.enRsCache = props.GetBool(EnRsCacheKey, c.enRsCache)
  366. c.localTimezone = int16(props.GetInt(TimeZoneKey, int(c.localTimezone), -720, 720))
  367. c.rsCacheSize = props.GetInt(RsCacheSizeKey, c.rsCacheSize, 0, int(INT32_MAX))
  368. c.rsRefreshFreq = props.GetInt(RsRefreshFreqKey, c.rsRefreshFreq, 0, int(INT32_MAX))
  369. c.loginMode = int32(props.GetInt(LoginModeKey, int(c.loginMode), 0, 4))
  370. c.loginStatus = props.GetInt(LoginStatusKey, c.loginStatus, 0, int(INT32_MAX))
  371. c.loginDscCtrl = props.GetBool(LoginDscCtrlKey, c.loginDscCtrl)
  372. c.switchTimes = int32(props.GetInt(SwitchTimesKey, int(c.switchTimes), 0, int(INT32_MAX)))
  373. c.switchInterval = props.GetInt(SwitchIntervalKey, c.switchInterval, 0, int(INT32_MAX))
  374. c.epSelector = int32(props.GetInt(EpSelectorKey, int(c.epSelector), 0, 1))
  375. c.loginEncrypt = props.GetBool(LoginEncryptKey, c.loginEncrypt)
  376. c.loginCertificate = props.GetTrimString(LoginCertificateKey, c.loginCertificate)
  377. c.dec2Double = props.GetBool(Dec2DoubleKey, c.dec2Double)
  378. parseLanguage(props.GetString(LanguageKey, ""))
  379. c.rwSeparate = props.GetBool(RwSeparateKey, c.rwSeparate)
  380. c.rwAutoDistribute = props.GetBool(RwAutoDistributeKey, c.rwAutoDistribute)
  381. c.rwPercent = int32(props.GetInt(RwPercentKey, int(c.rwPercent), 0, 100))
  382. c.rwHA = props.GetBool(RwHAKey, c.rwHA)
  383. c.rwStandbyRecoverTime = props.GetInt(RwStandbyRecoverTimeKey, c.rwStandbyRecoverTime, 0, int(INT32_MAX))
  384. c.rwIgnoreSql = props.GetBool(RwIgnoreSqlKey, c.rwIgnoreSql)
  385. c.doSwitch = int32(props.GetInt(DoSwitchKey, int(c.doSwitch), 0, 2))
  386. c.driverReconnect = props.GetBool(DriverReconnectKey, c.driverReconnect)
  387. c.parseCluster(props)
  388. c.cipherPath = props.GetTrimString(CipherPathKey, c.cipherPath)
  389. if props.GetBool(CompatibleOraKey, false) {
  390. c.compatibleMode = int(COMPATIBLE_MODE_ORACLE)
  391. }
  392. c.parseCompatibleMode(props)
  393. c.keyWords = props.GetStringArray(KeywordsKey, c.keyWords)
  394. c.appName = props.GetTrimString(AppNameKey, c.appName)
  395. c.osName = props.GetTrimString(OsNameKey, c.osName)
  396. c.mppLocal = props.GetBool(MppLocalKey, c.mppLocal)
  397. c.socketTimeout = props.GetInt(SocketTimeoutKey, c.socketTimeout, 0, int(INT32_MAX))
  398. c.connectTimeout = props.GetInt(ConnectTimeoutKey, c.connectTimeout, 0, int(INT32_MAX))
  399. c.sessionTimeout = props.GetInt(SessionTimeoutKey, c.sessionTimeout, 0, int(INT32_MAX))
  400. err := c.parseOsAuthType(props)
  401. if err != nil {
  402. return err
  403. }
  404. c.continueBatchOnError = props.GetBool(ContinueBatchOnErrorKey, c.continueBatchOnError)
  405. c.batchAllowMaxErrors = int32(props.GetInt(BatchAllowMaxErrorsKey, int(c.batchAllowMaxErrors), 0, int(INT32_MAX)))
  406. c.escapeProcess = props.GetBool(EscapeProcessKey, c.escapeProcess)
  407. c.autoCommit = props.GetBool(AutoCommitKey, c.autoCommit)
  408. c.maxRows = props.GetInt(MaxRowsKey, c.maxRows, 0, int(INT32_MAX))
  409. c.rowPrefetch = props.GetInt(RowPrefetchKey, c.rowPrefetch, 0, int(INT32_MAX))
  410. c.bufPrefetch = props.GetInt(BufPrefetchKey, c.bufPrefetch, int(Dm_build_76), int(Dm_build_77))
  411. c.lobMode = props.GetInt(LobModeKey, c.lobMode, 1, 2)
  412. c.stmtPoolMaxSize = props.GetInt(StmtPoolSizeKey, c.stmtPoolMaxSize, 0, int(INT32_MAX))
  413. c.ignoreCase = props.GetBool(IgnoreCaseKey, c.ignoreCase)
  414. c.alwayseAllowCommit = props.GetBool(AlwayseAllowCommitKey, c.alwayseAllowCommit)
  415. c.batchType = props.GetInt(BatchTypeKey, c.batchType, 1, 2)
  416. c.batchNotOnCall = props.GetBool(BatchNotOnCallKey, c.batchNotOnCall)
  417. c.isBdtaRS = props.GetBool(IsBdtaRSKey, c.isBdtaRS)
  418. c.sslFilesPath = props.GetTrimString(SslFilesPathKey, c.sslFilesPath)
  419. c.sslCertPath = props.GetTrimString(SslCertPathKey, c.sslCertPath)
  420. if c.sslCertPath == "" && c.sslFilesPath != "" {
  421. c.sslCertPath = filepath.Join(c.sslFilesPath, "client-cert.pem")
  422. }
  423. c.sslKeyPath = props.GetTrimString(SslKeyPathKey, c.sslKeyPath)
  424. if c.sslKeyPath == "" && c.sslFilesPath != "" {
  425. c.sslKeyPath = filepath.Join(c.sslKeyPath, "client-key.pem")
  426. }
  427. c.kerberosLoginConfPath = props.GetTrimString(KerberosLoginConfPathKey, c.kerberosLoginConfPath)
  428. c.uKeyName = props.GetTrimString(UKeyNameKey, c.uKeyName)
  429. c.uKeyPin = props.GetTrimString(UKeyPinKey, c.uKeyPin)
  430. c.svcConfPath = props.GetString("confPath", "")
  431. if props.GetBool(ColumnNameUpperCaseKey, false) {
  432. c.columnNameCase = COLUMN_NAME_UPPER_CASE
  433. }
  434. v := props.GetTrimString(ColumnNameCaseKey, "")
  435. if util.StringUtil.EqualsIgnoreCase(v, "upper") {
  436. c.columnNameCase = COLUMN_NAME_UPPER_CASE
  437. } else if util.StringUtil.EqualsIgnoreCase(v, "lower") {
  438. c.columnNameCase = COLUMN_NAME_LOWER_CASE
  439. }
  440. c.schema = props.GetTrimString(SchemaKey, c.schema)
  441. c.logLevel = ParseLogLevel(props)
  442. LogLevel = c.logLevel
  443. c.logDir = util.StringUtil.FormatDir(props.GetTrimString(LogDirKey, LogDirDef))
  444. LogDir = c.logDir
  445. c.logBufferSize = props.GetInt(LogBufferSizeKey, LogBufferSizeDef, 1, int(INT32_MAX))
  446. LogBufferSize = c.logBufferSize
  447. c.logFlushFreq = props.GetInt(LogFlushFreqKey, LogFlushFreqDef, 1, int(INT32_MAX))
  448. LogFlushFreq = c.logFlushFreq
  449. c.logFlushQueueSize = props.GetInt(LogFlusherQueueSizeKey, LogFlushQueueSizeDef, 1, int(INT32_MAX))
  450. LogFlushQueueSize = c.logFlushQueueSize
  451. c.statEnable = props.GetBool(StatEnableKey, StatEnableDef)
  452. StatEnable = c.statEnable
  453. c.statDir = util.StringUtil.FormatDir(props.GetTrimString(StatDirKey, StatDirDef))
  454. StatDir = c.statDir
  455. c.statFlushFreq = props.GetInt(StatFlushFreqKey, StatFlushFreqDef, 1, int(INT32_MAX))
  456. StatFlushFreq = c.statFlushFreq
  457. c.statHighFreqSqlCount = props.GetInt(StatHighFreqSqlCountKey, StatHighFreqSqlCountDef, 0, 1000)
  458. StatHighFreqSqlCount = c.statHighFreqSqlCount
  459. c.statSlowSqlCount = props.GetInt(StatSlowSqlCountKey, StatSlowSqlCountDef, 0, 1000)
  460. StatSlowSqlCount = c.statSlowSqlCount
  461. c.statSqlMaxCount = props.GetInt(StatSqlMaxCountKey, StatSqlMaxCountDef, 0, 100000)
  462. StatSqlMaxCount = c.statSqlMaxCount
  463. c.parseStatSqlRemoveMode(props)
  464. return nil
  465. }
  466. func (c *DmConnector) parseOsAuthType(props *Properties) error {
  467. value := props.GetString(OsAuthTypeKey, "")
  468. if value != "" && !util.StringUtil.IsDigit(value) {
  469. if util.StringUtil.EqualsIgnoreCase(value, "ON") {
  470. c.osAuthType = Dm_build_74
  471. } else if util.StringUtil.EqualsIgnoreCase(value, "SYSDBA") {
  472. c.osAuthType = Dm_build_70
  473. } else if util.StringUtil.EqualsIgnoreCase(value, "SYSAUDITOR") {
  474. c.osAuthType = Dm_build_72
  475. } else if util.StringUtil.EqualsIgnoreCase(value, "SYSSSO") {
  476. c.osAuthType = Dm_build_71
  477. } else if util.StringUtil.EqualsIgnoreCase(value, "AUTO") {
  478. c.osAuthType = Dm_build_73
  479. } else if util.StringUtil.EqualsIgnoreCase(value, "OFF") {
  480. c.osAuthType = Dm_build_69
  481. }
  482. } else {
  483. c.osAuthType = byte(props.GetInt(OsAuthTypeKey, int(c.osAuthType), 0, 4))
  484. }
  485. if c.user == "" && c.osAuthType == Dm_build_69 {
  486. c.user = "SYSDBA"
  487. } else if c.osAuthType != Dm_build_69 && c.user != "" {
  488. return ECGO_OSAUTH_ERROR.throw()
  489. } else if c.osAuthType != Dm_build_69 {
  490. c.user = os.Getenv("user")
  491. c.password = ""
  492. }
  493. return nil
  494. }
  495. func (c *DmConnector) parseCompatibleMode(props *Properties) {
  496. value := props.GetString(CompatibleModeKey, "")
  497. if value != "" && !util.StringUtil.IsDigit(value) {
  498. if util.StringUtil.EqualsIgnoreCase(value, "oracle") {
  499. c.compatibleMode = COMPATIBLE_MODE_ORACLE
  500. } else if util.StringUtil.EqualsIgnoreCase(value, "mysql") {
  501. c.compatibleMode = COMPATIBLE_MODE_MYSQL
  502. }
  503. } else {
  504. c.compatibleMode = props.GetInt(CompatibleModeKey, c.compatibleMode, 0, 2)
  505. }
  506. }
  507. func (c *DmConnector) parseStatSqlRemoveMode(props *Properties) {
  508. value := props.GetString(StatSqlRemoveModeKey, "")
  509. if value != "" && !util.StringUtil.IsDigit(value) {
  510. if util.StringUtil.EqualsIgnoreCase("oldest", value) || util.StringUtil.EqualsIgnoreCase("eldest", value) {
  511. c.statSqlRemoveMode = STAT_SQL_REMOVE_OLDEST
  512. } else if util.StringUtil.EqualsIgnoreCase("latest", value) {
  513. c.statSqlRemoveMode = STAT_SQL_REMOVE_LATEST
  514. }
  515. } else {
  516. c.statSqlRemoveMode = props.GetInt(StatSqlRemoveModeKey, StatSqlRemoveModeDef, 1, 2)
  517. }
  518. }
  519. func (c *DmConnector) parseCluster(props *Properties) {
  520. value := props.GetTrimString(ClusterKey, "")
  521. if util.StringUtil.EqualsIgnoreCase(value, "DSC") {
  522. c.cluster = CLUSTER_TYPE_DSC
  523. } else if util.StringUtil.EqualsIgnoreCase(value, "RW") {
  524. c.cluster = CLUSTER_TYPE_RW
  525. } else if util.StringUtil.EqualsIgnoreCase(value, "DW") {
  526. c.cluster = CLUSTER_TYPE_DW
  527. } else if util.StringUtil.EqualsIgnoreCase(value, "MPP") {
  528. c.cluster = CLUSTER_TYPE_MPP
  529. } else {
  530. c.cluster = CLUSTER_TYPE_NORMAL
  531. }
  532. }
  533. func (c *DmConnector) parseDSN(dsn string) (*Properties, string, error) {
  534. var dsnProps = NewProperties()
  535. url, err := url.Parse(dsn)
  536. if err != nil {
  537. return nil, "", err
  538. }
  539. if url.Scheme != "dm" {
  540. return nil, "", DSN_INVALID_SCHEMA
  541. }
  542. if url.User != nil {
  543. c.user = url.User.Username()
  544. c.password, _ = url.User.Password()
  545. }
  546. q := url.Query()
  547. for k := range q {
  548. dsnProps.Set(k, q.Get(k))
  549. }
  550. return dsnProps, url.Host, nil
  551. }
  552. func (c *DmConnector) BuildDSN() string {
  553. var buf bytes.Buffer
  554. buf.WriteString("dm://")
  555. if len(c.user) > 0 {
  556. buf.WriteString(url.QueryEscape(c.user))
  557. if len(c.password) > 0 {
  558. buf.WriteByte(':')
  559. buf.WriteString(url.QueryEscape(c.password))
  560. }
  561. buf.WriteByte('@')
  562. }
  563. if len(c.host) > 0 {
  564. buf.WriteString(c.host)
  565. if c.port > 0 {
  566. buf.WriteByte(':')
  567. buf.WriteString(strconv.Itoa(int(c.port)))
  568. }
  569. }
  570. hasParam := false
  571. if c.connectTimeout > 0 {
  572. if hasParam {
  573. buf.WriteString("&timeout=")
  574. } else {
  575. buf.WriteString("?timeout=")
  576. hasParam = true
  577. }
  578. buf.WriteString(strconv.Itoa(c.connectTimeout))
  579. }
  580. return buf.String()
  581. }
  582. func (c *DmConnector) mergeConfigs(dsn string) error {
  583. props, host, err := c.parseDSN(dsn)
  584. if err != nil {
  585. return err
  586. }
  587. driverInit(props.GetString("svcConfPath", ""))
  588. addressRemapStr := props.GetTrimString(AddressRemapKey, "")
  589. userRemapStr := props.GetTrimString(UserRemapKey, "")
  590. if addressRemapStr == "" {
  591. addressRemapStr = GlobalProperties.GetTrimString(AddressRemapKey, "")
  592. }
  593. if userRemapStr == "" {
  594. userRemapStr = GlobalProperties.GetTrimString(UserRemapKey, "")
  595. }
  596. host = c.remap(host, addressRemapStr)
  597. c.user = c.remap(c.user, userRemapStr)
  598. if a := props.GetTrimString(host, ""); a != "" {
  599. if strings.HasPrefix(a, "(") && strings.HasSuffix(a, ")") {
  600. a = strings.TrimSpace(a[1 : len(a)-1])
  601. }
  602. c.group = parseServerName(host, a)
  603. if c.group != nil {
  604. c.group.props = NewProperties()
  605. c.group.props.SetProperties(GlobalProperties)
  606. }
  607. } else if group, ok := ServerGroupMap[strings.ToLower(host)]; ok {
  608. c.group = group
  609. } else {
  610. host, port, err := net.SplitHostPort(host)
  611. if err == nil {
  612. ip := net.ParseIP(host)
  613. var v4InV6Prefix = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}
  614. if ip != nil && len(ip) == net.IPv6len && !bytes.Equal(ip[0:12], v4InV6Prefix) {
  615. host = "[" + host + "]"
  616. }
  617. }
  618. c.host = host
  619. tmpPort, err := strconv.Atoi(port)
  620. if err != nil {
  621. c.port = portDef
  622. } else {
  623. c.port = int32(tmpPort)
  624. }
  625. c.group = newEPGroup(c.host+":"+strconv.Itoa(int(c.port)), []*ep{newEP(c.host, c.port)})
  626. }
  627. props.SetDiffProperties(c.group.props)
  628. props.SetDiffProperties(GlobalProperties)
  629. if props.GetBool(RwSeparateKey, false) {
  630. props.SetIfNotExist(LoginModeKey, strconv.Itoa(int(LOGIN_MODE_PRIMARY_ONLY)))
  631. props.SetIfNotExist(LoginStatusKey, strconv.Itoa(int(SERVER_STATUS_OPEN)))
  632. props.SetIfNotExist(DoSwitchKey, "true")
  633. }
  634. if err = c.setAttributes(props); err != nil {
  635. return err
  636. }
  637. return nil
  638. }
  639. func (c *DmConnector) remap(origin string, cfgStr string) string {
  640. if cfgStr == "" || origin == "" {
  641. return origin
  642. }
  643. maps := regexp.MustCompile("\\(.*?,.*?\\)").FindAllString(cfgStr, -1)
  644. for _, kvStr := range maps {
  645. kv := strings.Split(strings.TrimSpace(kvStr[1:len(kvStr)-1]), ",")
  646. if util.StringUtil.Equals(strings.TrimSpace(kv[0]), origin) {
  647. return strings.TrimSpace(kv[1])
  648. }
  649. }
  650. return origin
  651. }
  652. func (c *DmConnector) Connect(ctx context.Context) (driver.Conn, error) {
  653. c.mu.Lock()
  654. defer c.mu.Unlock()
  655. return c.filterChain.reset().DmConnectorConnect(c, ctx)
  656. }
  657. func (c *DmConnector) Driver() driver.Driver {
  658. c.mu.Lock()
  659. defer c.mu.Unlock()
  660. return c.filterChain.reset().DmConnectorDriver(c)
  661. }
  662. func (c *DmConnector) connect(ctx context.Context) (*DmConnection, error) {
  663. if c.group != nil && len(c.group.epList) > 0 {
  664. return c.group.connect(c)
  665. } else {
  666. return c.connectSingle(ctx)
  667. }
  668. }
  669. func (c *DmConnector) driver() *DmDriver {
  670. return c.dmDriver
  671. }
  672. func (c *DmConnector) connectSingle(ctx context.Context) (*DmConnection, error) {
  673. var err error
  674. var dc = &DmConnection{
  675. closech: make(chan struct{}),
  676. dmConnector: c,
  677. autoCommit: c.autoCommit,
  678. }
  679. dc.createFilterChain(c, nil)
  680. dc.objId = -1
  681. dc.init()
  682. dc.Access, err = dm_build_1357(ctx, dc)
  683. if err != nil {
  684. return nil, err
  685. }
  686. dc.startWatcher()
  687. if err = dc.watchCancel(ctx); err != nil {
  688. return nil, err
  689. }
  690. defer dc.finish()
  691. if err = dc.Access.dm_build_1402(); err != nil {
  692. if !dc.closed.IsSet() {
  693. close(dc.closech)
  694. if dc.Access != nil {
  695. dc.Access.Close()
  696. }
  697. dc.closed.Set(true)
  698. }
  699. return nil, err
  700. }
  701. if c.schema != "" {
  702. _, err = dc.exec("set schema "+c.schema, nil)
  703. if err != nil {
  704. return nil, err
  705. }
  706. }
  707. return dc, nil
  708. }