Skip to content

Commit 113836b

Browse files
committed
Mysql, initial fix connecting to database (mariadb is pending)
Error: test_mysql_strict_mode_disabled(MySQLConnectionTest): ActiveRecord::ConnectionNotEstablished: adapter requires :driver class and jdbc :url arjdbc/jdbc/RubyJdbcConnection.java:532:in `initialize' org/jruby/RubyClass.java:935:in `new' /home/jessec/bryk/vendor_gems/activerecord-jdbc-adapter/lib/arjdbc/mysql/adapter.rb:47:in `new_client' /home/jessec/bryk/vendor_gems/activerecord-jdbc-adapter/lib/arjdbc/abstract/connection_management.rb:43:in `connect' /home/jessec/bryk/vendor_gems/activerecord-jdbc-adapter/lib/arjdbc/abstract/connection_management.rb:53:in `reconnect' /home/jessec/.gem/jruby/3.1.4/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:662:in `block in reconnect!' /home/jessec/.gem/jruby/3.1.4/gems/activesupport-7.2.2.1/lib/active_support/concurrency/null_lock.rb:9:in `synchronize' /home/jessec/.gem/jruby/3.1.4/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:661:in `reconnect!' /home/jessec/.gem/jruby/3.1.4/gems/activerecord-7.2.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:763:in `block in verify!' /home/jessec/.gem/jruby/3.1.4/gems/activesupport-7.2.2.1/lib/active_support/concurrency/null_lock.rb:9:in `synchronize' ...
1 parent 6365199 commit 113836b

File tree

3 files changed

+157
-2
lines changed

3 files changed

+157
-2
lines changed

lib/arjdbc/mysql.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
require 'arjdbc'
22
require 'arjdbc/mysql/adapter'
3-
require 'arjdbc/mysql/connection_methods'
3+
# require 'arjdbc/mysql/connection_methods'

lib/arjdbc/mysql/adapter.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
require 'arjdbc/abstract/statement_cache'
1212
require 'arjdbc/abstract/transaction_support'
1313

14+
require "arjdbc/mysql/adapter_hash_config"
15+
1416
require "arjdbc/abstract/relation_query_attribute_monkey_patch"
1517

1618
module ActiveRecord
@@ -34,6 +36,7 @@ class Mysql2Adapter < AbstractMysqlAdapter
3436
include ArJdbc::Abstract::TransactionSupport
3537

3638
include ArJdbc::MySQL
39+
include ArJdbc::MysqlConfig
3740

3841
class << self
3942
def jdbc_connection_class
@@ -68,14 +71,17 @@ def initialize(...)
6871

6972
@config[:flags] ||= 0
7073

74+
# assign arjdbc extra connection params
75+
conn_params = build_connection_config(@config.compact)
76+
7177
# JDBC mysql appears to use found rows by default: https://dev.mysql.com/doc/connector-j/en/connector-j-connp-props-connection.html
7278
# if @config[:flags].kind_of? Array
7379
# @config[:flags].push "FOUND_ROWS"
7480
# else
7581
# @config[:flags] |= ::Mysql2::Client::FOUND_ROWS
7682
# end
7783

78-
@connection_parameters ||= @config
84+
@connection_parameters = conn_params
7985
end
8086

8187
def self.database_exists?(config)
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
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

Comments
 (0)