|
| 1 | +# frozen_string_literal: true |
| 2 | + |
| 3 | +module ArJdbc |
| 4 | + module MysqlConfig |
| 5 | + def build_connection_config(config) |
| 6 | + config = config.deep_dup |
| 7 | + |
| 8 | + load_jdbc_driver |
| 9 | + |
| 10 | + config[:driver] ||= database_driver_name |
| 11 | + |
| 12 | + host = (config[:host] ||= "localhost") |
| 13 | + port = (config[:port] ||= 3306) |
| 14 | + |
| 15 | + # jdbc:mysql://[host][,failoverhost...][:port]/[database] |
| 16 | + # - alternate fail-over syntax: [host:port],[host:port]/[database] |
| 17 | + config[:url] ||= "jdbc:mysql://#{host}:#{port}/#{config[:database]}" |
| 18 | + |
| 19 | + config[:properties] = build_properties(config) |
| 20 | + |
| 21 | + config |
| 22 | + end |
| 23 | + |
| 24 | + private |
| 25 | + |
| 26 | + def load_jdbc_driver |
| 27 | + require "jdbc/mysql" |
| 28 | + |
| 29 | + ::Jdbc::MySQL.load_driver(:require) if defined?(::Jdbc::MySQL.load_driver) |
| 30 | + rescue LoadError |
| 31 | + # assuming driver.jar is on the class-path |
| 32 | + end |
| 33 | + |
| 34 | + def database_driver_name |
| 35 | + return ::Jdbc::MySQL.driver_name if defined?(::Jdbc::MySQL.driver_name) |
| 36 | + |
| 37 | + "com.mysql.jdbc.Driver" |
| 38 | + end |
| 39 | + |
| 40 | + def build_properties(config) |
| 41 | + properties = config[:properties] || {} |
| 42 | + |
| 43 | + properties["zeroDateTimeBehavior"] ||= "CONVERT_TO_NULL" |
| 44 | + |
| 45 | + properties["jdbcCompliantTruncation"] ||= false |
| 46 | + |
| 47 | + charset_name = convert_mysql_encoding(config) |
| 48 | + |
| 49 | + # do not set characterEncoding |
| 50 | + if charset_name.eql?(false) |
| 51 | + properties["character_set_server"] = config[:encoding] || "utf8" |
| 52 | + else |
| 53 | + properties["characterEncoding"] = charset_name |
| 54 | + end |
| 55 | + |
| 56 | + # driver also executes: "SET NAMES " + (useutf8mb4 ? "utf8mb4" : "utf8") |
| 57 | + # thus no need to do it on configure_connection : |
| 58 | + config[:encoding] = nil if config.key?(:encoding) |
| 59 | + |
| 60 | + properties["connectionCollation"] ||= config[:collation] if config[:collation] |
| 61 | + |
| 62 | + properties["autoReconnect"] ||= reconnect.to_s unless config[:reconnect].nil? |
| 63 | + |
| 64 | + properties["noDatetimeStringSync"] = true unless properties.key?("noDatetimeStringSync") |
| 65 | + |
| 66 | + sslcert = config[:sslcert] |
| 67 | + sslca = config[:sslca] |
| 68 | + |
| 69 | + if config[:sslkey] || sslcert |
| 70 | + properties["useSSL"] ||= true |
| 71 | + properties["requireSSL"] ||= true |
| 72 | + properties["clientCertificateKeyStoreUrl"] ||= java.io.File.new(sslcert).to_url.to_s if sslcert |
| 73 | + |
| 74 | + if sslca |
| 75 | + properties["trustCertificateKeyStoreUrl"] ||= java.io.File.new(sslca).to_url.to_s |
| 76 | + else |
| 77 | + properties["verifyServerCertificate"] ||= false |
| 78 | + end |
| 79 | + else |
| 80 | + # According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection |
| 81 | + # must be established by default if explicit option isn't set : |
| 82 | + properties["useSSL"] ||= false |
| 83 | + end |
| 84 | + |
| 85 | + # disables the effect of 'useTimezone' |
| 86 | + properties["useLegacyDatetimeCode"] = false |
| 87 | + |
| 88 | + properties |
| 89 | + end |
| 90 | + |
| 91 | + # See https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-charsets.html |
| 92 | + # to charset-name (characterEncoding=...) |
| 93 | + def convert_mysql_encoding(config) |
| 94 | + # NOTE: this is "better" than passing what users are used to set on MRI |
| 95 | + # e.g. 'utf8mb4' will fail cause the driver will check for a Java charset |
| 96 | + # ... it's smart enough to detect utf8mb4 from server variables : |
| 97 | + # "character_set_client" && "character_set_connection" (thus UTF-8) |
| 98 | + encoding = config.key?(:encoding) ? config[:encoding] : "utf8" |
| 99 | + |
| 100 | + value = MYSQL_ENCODINGS[encoding] |
| 101 | + |
| 102 | + return false if value == false |
| 103 | + |
| 104 | + value || encoding |
| 105 | + end |
| 106 | + |
| 107 | + MYSQL_ENCODINGS = { |
| 108 | + "big5" => "Big5", |
| 109 | + "dec8" => nil, |
| 110 | + "hp8" => nil, |
| 111 | + "latin1" => "Cp1252", |
| 112 | + "latin2" => "ISO8859_2", |
| 113 | + "swe7" => nil, |
| 114 | + "ascii" => "US-ASCII", |
| 115 | + "ujis" => "EUC_JP", |
| 116 | + "sjis" => "SJIS", |
| 117 | + "hebrew" => "ISO8859_8", |
| 118 | + "tis620" => "TIS620", |
| 119 | + "euckr" => "EUC_KR", |
| 120 | + "gb2312" => "EUC_CN", |
| 121 | + "greek" => "ISO8859_7", |
| 122 | + "cp1250" => "Cp1250", |
| 123 | + "gbk" => "GBK", |
| 124 | + "armscii8" => nil, |
| 125 | + "ucs2" => "UnicodeBig", |
| 126 | + "cp866" => "Cp866", |
| 127 | + "keybcs2" => nil, |
| 128 | + "macce" => "MacCentralEurope", |
| 129 | + "macroman" => "MacRoman", |
| 130 | + "cp1251" => "Cp1251", |
| 131 | + "cp1256" => "Cp1256", |
| 132 | + "cp1257" => "Cp1257", |
| 133 | + "binary" => false, |
| 134 | + "geostd8" => nil, |
| 135 | + "cp932" => "Cp932", |
| 136 | + "utf8" => "UTF-8", |
| 137 | + "utf8mb4" => false, |
| 138 | + "utf16" => false, |
| 139 | + "utf32" => false, |
| 140 | + # "cp850" => "Cp850", |
| 141 | + # "koi8r" => "KOI8-R", |
| 142 | + # "koi8u" => "KOI8-R", |
| 143 | + # "latin5" => "ISO-8859-9", |
| 144 | + # "cp852" => "CP852", |
| 145 | + # "latin7" => "ISO-8859-13", |
| 146 | + # "eucjpms" => "eucJP-ms" |
| 147 | + }.freeze |
| 148 | + end |
| 149 | +end |
0 commit comments