activerecord-jdbc-adapter 70.2-java → 72.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +26 -26
- data/.gitignore +8 -0
- data/Gemfile +17 -4
- data/README.md +10 -5
- data/RUNNING_TESTS.md +36 -0
- data/activerecord-jdbc-adapter.gemspec +2 -2
- data/lib/arjdbc/abstract/connection_management.rb +25 -10
- data/lib/arjdbc/abstract/core.rb +15 -13
- data/lib/arjdbc/abstract/database_statements.rb +36 -36
- data/lib/arjdbc/abstract/relation_query_attribute_monkey_patch.rb +24 -0
- data/lib/arjdbc/abstract/statement_cache.rb +2 -7
- data/lib/arjdbc/abstract/transaction_support.rb +39 -22
- data/lib/arjdbc/jdbc/adapter.rb +0 -1
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/column.rb +0 -34
- data/lib/arjdbc/jdbc/connection_methods.rb +1 -1
- data/lib/arjdbc/mysql/adapter.rb +108 -32
- data/lib/arjdbc/mysql/adapter_hash_config.rb +159 -0
- data/lib/arjdbc/mysql.rb +1 -1
- data/lib/arjdbc/postgresql/adapter.rb +267 -114
- data/lib/arjdbc/postgresql/adapter_hash_config.rb +98 -0
- data/lib/arjdbc/postgresql/base/array_encoder.rb +3 -1
- data/lib/arjdbc/postgresql/database_statements.rb +20 -0
- data/lib/arjdbc/postgresql/oid_types.rb +10 -29
- data/lib/arjdbc/postgresql/schema_statements.rb +57 -0
- data/lib/arjdbc/postgresql.rb +1 -1
- data/lib/arjdbc/sqlite3/adapter.rb +343 -172
- data/lib/arjdbc/sqlite3/adapter_hash_config.rb +91 -0
- data/lib/arjdbc/sqlite3/column.rb +117 -0
- data/lib/arjdbc/sqlite3/connection_methods.rb +7 -2
- data/lib/arjdbc/sqlite3/pragmas.rb +105 -0
- data/lib/arjdbc/sqlite3.rb +1 -1
- data/lib/arjdbc/version.rb +1 -1
- data/lib/arjdbc.rb +13 -1
- data/rakelib/02-test.rake +2 -2
- data/rakelib/rails.rake +2 -0
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +9 -2
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +12 -5
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +14 -3
- metadata +15 -11
- data/lib/arjdbc/jdbc/base_ext.rb +0 -17
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ArJdbc
|
4
|
+
module PostgreSQLConfig
|
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] ||= config[:hostaddr] || ENV["PGHOST"] || "localhost")
|
13
|
+
port = (config[:port] ||= ENV["PGPORT"] || 5432)
|
14
|
+
database = config[:database] || config[:dbname] || ENV["PGDATABASE"]
|
15
|
+
|
16
|
+
app = config[:application_name] || config[:appname] || config[:application]
|
17
|
+
|
18
|
+
config[:url] ||= if app
|
19
|
+
"jdbc:postgresql://#{host}:#{port}/#{database}?ApplicationName=#{app}"
|
20
|
+
else
|
21
|
+
"jdbc:postgresql://#{host}:#{port}/#{database}"
|
22
|
+
end
|
23
|
+
|
24
|
+
config[:url] << config[:pg_params] if config[:pg_params]
|
25
|
+
|
26
|
+
config[:username] ||= config[:user] || ENV["PGUSER"] || ENV_JAVA["user.name"]
|
27
|
+
config[:password] ||= ENV["PGPASSWORD"] unless config.key?(:password)
|
28
|
+
|
29
|
+
config[:properties] = build_properties(config)
|
30
|
+
|
31
|
+
config
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def load_jdbc_driver
|
37
|
+
require "jdbc/postgres"
|
38
|
+
|
39
|
+
::Jdbc::Postgres.load_driver(:require) if defined?(::Jdbc::Postgres.load_driver)
|
40
|
+
rescue LoadError
|
41
|
+
# assuming driver.jar is on the class-path
|
42
|
+
end
|
43
|
+
|
44
|
+
def database_driver_name
|
45
|
+
return ::Jdbc::Postgres.driver_name if defined?(::Jdbc::Postgres.driver_name)
|
46
|
+
|
47
|
+
"org.postgresql.Driver"
|
48
|
+
end
|
49
|
+
|
50
|
+
def build_properties(config)
|
51
|
+
properties = config[:properties] || {}
|
52
|
+
|
53
|
+
# PG :connect_timeout - maximum time to wait for connection to succeed
|
54
|
+
connect_timeout = config[:connect_timeout] || ENV["PGCONNECT_TIMEOUT"]
|
55
|
+
|
56
|
+
properties["socketTimeout"] ||= connect_timeout if connect_timeout
|
57
|
+
|
58
|
+
login_timeout = config[:login_timeout]
|
59
|
+
|
60
|
+
properties["loginTimeout"] ||= login_timeout if login_timeout
|
61
|
+
|
62
|
+
sslmode = config.key?(:sslmode) ? config[:sslmode] : config[:requiressl]
|
63
|
+
# NOTE: makes not much sense since this needs some JVM options :
|
64
|
+
sslmode = ENV["PGSSLMODE"] || ENV["PGREQUIRESSL"] if sslmode.nil?
|
65
|
+
|
66
|
+
# PG :sslmode - disable|allow|prefer|require
|
67
|
+
unless sslmode.nil? || !(sslmode == true || sslmode.to_s == "require")
|
68
|
+
# JRuby/JVM needs to be started with :
|
69
|
+
# -Djavax.net.ssl.trustStore=mystore -Djavax.net.ssl.trustStorePassword=...
|
70
|
+
# or a non-validating connection might be used (for testing) :
|
71
|
+
# :sslfactory = 'org.postgresql.ssl.NonValidatingFactory'
|
72
|
+
|
73
|
+
if config[:driver].start_with?("org.postgresql.")
|
74
|
+
properties["sslfactory"] ||= "org.postgresql.ssl.NonValidatingFactory"
|
75
|
+
end
|
76
|
+
|
77
|
+
properties["ssl"] ||= "true"
|
78
|
+
end
|
79
|
+
|
80
|
+
properties["tcpKeepAlive"] ||= config[:keepalives] if config.key?(:keepalives)
|
81
|
+
properties["kerberosServerName"] ||= config[:krbsrvname] if config[:krbsrvname]
|
82
|
+
|
83
|
+
prepared_statements = config.fetch(:prepared_statements, true)
|
84
|
+
|
85
|
+
prepared_statements = false if prepared_statements == "false"
|
86
|
+
|
87
|
+
if prepared_statements
|
88
|
+
# this makes the pgjdbc driver handle hot compatibility internally
|
89
|
+
properties["autosave"] ||= "conservative"
|
90
|
+
else
|
91
|
+
# If prepared statements are off, lets make sure they are really *off*
|
92
|
+
properties["prepareThreshold"] = 0
|
93
|
+
end
|
94
|
+
|
95
|
+
properties
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -12,7 +12,9 @@ module ActiveRecord::ConnectionAdapters::PostgreSQL::OID
|
|
12
12
|
'text'.freeze
|
13
13
|
else
|
14
14
|
base_type = name.chomp('[]').to_sym
|
15
|
-
ActiveRecord::Base.connection
|
15
|
+
ActiveRecord::Base.with_connection do |connection|
|
16
|
+
connection.native_database_types[base_type][:name]
|
17
|
+
end
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ArJdbc
|
4
|
+
module PostgreSQL
|
5
|
+
module DatabaseStatements
|
6
|
+
def explain(arel, binds = [], options = [])
|
7
|
+
sql = build_explain_clause(options) + " " + to_sql(arel, binds)
|
8
|
+
|
9
|
+
result = internal_exec_query(sql, "EXPLAIN", binds)
|
10
|
+
ActiveRecord::ConnectionAdapters::PostgreSQL::ExplainPrettyPrinter.new.pp(result)
|
11
|
+
end
|
12
|
+
|
13
|
+
def build_explain_clause(options = [])
|
14
|
+
return "EXPLAIN" if options.empty?
|
15
|
+
|
16
|
+
"EXPLAIN (#{options.join(", ").upcase})"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -67,28 +67,6 @@ module ArJdbc
|
|
67
67
|
|
68
68
|
# @private
|
69
69
|
module OIDTypes
|
70
|
-
|
71
|
-
# @override
|
72
|
-
def enable_extension(name)
|
73
|
-
result = super(name)
|
74
|
-
@extensions = nil
|
75
|
-
reload_type_map
|
76
|
-
result
|
77
|
-
end
|
78
|
-
|
79
|
-
# @override
|
80
|
-
def disable_extension(name)
|
81
|
-
result = super(name)
|
82
|
-
@extensions = nil
|
83
|
-
reload_type_map
|
84
|
-
result
|
85
|
-
end
|
86
|
-
|
87
|
-
# @override
|
88
|
-
def extensions
|
89
|
-
@extensions ||= super
|
90
|
-
end
|
91
|
-
|
92
70
|
def get_oid_type(oid, fmod, column_name, sql_type = '') # :nodoc:
|
93
71
|
# Note: type_map is storing a bunch of oid type prefixed with a namespace even
|
94
72
|
# if they are not namespaced (e.g. ""."oidvector"). builtin types which are
|
@@ -118,8 +96,15 @@ module ArJdbc
|
|
118
96
|
end
|
119
97
|
|
120
98
|
def reload_type_map
|
121
|
-
|
99
|
+
@lock.synchronize do
|
100
|
+
if @type_map
|
101
|
+
type_map.clear
|
102
|
+
else
|
103
|
+
@type_map = Type::HashLookupTypeMap.new
|
104
|
+
end
|
105
|
+
|
122
106
|
initialize_type_map
|
107
|
+
end
|
123
108
|
end
|
124
109
|
|
125
110
|
def initialize_type_map_inner(m)
|
@@ -127,8 +112,8 @@ module ArJdbc
|
|
127
112
|
m.register_type "int4", Type::Integer.new(limit: 4)
|
128
113
|
m.register_type "int8", Type::Integer.new(limit: 8)
|
129
114
|
m.register_type "oid", OID::Oid.new
|
130
|
-
m.register_type "float4", Type::Float.new
|
131
|
-
m.
|
115
|
+
m.register_type "float4", Type::Float.new(limit: 24)
|
116
|
+
m.register_type "float8", Type::Float.new
|
132
117
|
m.register_type "text", Type::Text.new
|
133
118
|
register_class_with_limit m, "varchar", Type::String
|
134
119
|
m.alias_type "char", "varchar"
|
@@ -274,10 +259,6 @@ module ArJdbc
|
|
274
259
|
$1.to_i if sql_type =~ /\((\d+)(,\d+)?\)/
|
275
260
|
end
|
276
261
|
|
277
|
-
def extract_limit(sql_type)
|
278
|
-
$1.to_i if sql_type =~ /\((.*)\)/
|
279
|
-
end
|
280
|
-
|
281
262
|
# Support arrays/ranges for defining attributes that don't exist in the db
|
282
263
|
ActiveRecord::Type.add_modifier({ array: true }, OID::Array, adapter: :postgresql)
|
283
264
|
ActiveRecord::Type.add_modifier({ range: true }, OID::Range, adapter: :postgresql)
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ArJdbc
|
4
|
+
module PostgreSQL
|
5
|
+
module SchemaStatements
|
6
|
+
ForeignKeyDefinition = ActiveRecord::ConnectionAdapters::ForeignKeyDefinition
|
7
|
+
Utils = ActiveRecord::ConnectionAdapters::PostgreSQL::Utils
|
8
|
+
|
9
|
+
def foreign_keys(table_name)
|
10
|
+
scope = quoted_scope(table_name)
|
11
|
+
fk_info = internal_exec_query(<<~SQL, "SCHEMA", allow_retry: true, materialize_transactions: false)
|
12
|
+
SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete, c.convalidated AS valid, c.condeferrable AS deferrable, c.condeferred AS deferred, c.conkey, c.confkey, c.conrelid, c.confrelid
|
13
|
+
FROM pg_constraint c
|
14
|
+
JOIN pg_class t1 ON c.conrelid = t1.oid
|
15
|
+
JOIN pg_class t2 ON c.confrelid = t2.oid
|
16
|
+
JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
|
17
|
+
JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
|
18
|
+
JOIN pg_namespace t3 ON c.connamespace = t3.oid
|
19
|
+
WHERE c.contype = 'f'
|
20
|
+
AND t1.relname = #{scope[:name]}
|
21
|
+
AND t3.nspname = #{scope[:schema]}
|
22
|
+
ORDER BY c.conname
|
23
|
+
SQL
|
24
|
+
|
25
|
+
fk_info.map do |row|
|
26
|
+
to_table = Utils.unquote_identifier(row["to_table"])
|
27
|
+
# conkey = row["conkey"].scan(/\d+/).map(&:to_i)
|
28
|
+
# confkey = row["confkey"].scan(/\d+/).map(&:to_i)
|
29
|
+
conkey = row["conkey"]
|
30
|
+
confkey = row["confkey"]
|
31
|
+
|
32
|
+
if conkey.size > 1
|
33
|
+
column = column_names_from_column_numbers(row["conrelid"], conkey)
|
34
|
+
primary_key = column_names_from_column_numbers(row["confrelid"], confkey)
|
35
|
+
else
|
36
|
+
column = Utils.unquote_identifier(row["column"])
|
37
|
+
primary_key = row["primary_key"]
|
38
|
+
end
|
39
|
+
|
40
|
+
options = {
|
41
|
+
column: column,
|
42
|
+
name: row["name"],
|
43
|
+
primary_key: primary_key
|
44
|
+
}
|
45
|
+
|
46
|
+
options[:on_delete] = extract_foreign_key_action(row["on_delete"])
|
47
|
+
options[:on_update] = extract_foreign_key_action(row["on_update"])
|
48
|
+
options[:deferrable] = extract_constraint_deferrable(row["deferrable"], row["deferred"])
|
49
|
+
|
50
|
+
options[:validate] = row["valid"]
|
51
|
+
|
52
|
+
ForeignKeyDefinition.new(table_name, to_table, options)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/arjdbc/postgresql.rb
CHANGED