activerecord-jdbc-adapter 1.3.0.beta1 → 1.3.0.beta2
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.
- data/.gitignore +12 -11
- data/.travis.yml +36 -7
- data/Appraisals +3 -3
- data/Gemfile +1 -1
- data/Gemfile.lock +13 -6
- data/History.txt +64 -0
- data/README.md +8 -1
- data/Rakefile +3 -1
- data/gemfiles/rails23.gemfile +1 -1
- data/gemfiles/rails23.gemfile.lock +6 -5
- data/gemfiles/rails30.gemfile +1 -1
- data/gemfiles/rails30.gemfile.lock +7 -6
- data/gemfiles/rails31.gemfile +1 -1
- data/gemfiles/rails31.gemfile.lock +6 -5
- data/gemfiles/rails32.gemfile +1 -1
- data/gemfiles/rails32.gemfile.lock +6 -5
- data/gemfiles/rails40.gemfile +2 -4
- data/gemfiles/rails40.gemfile.lock +37 -51
- data/lib/active_record/connection_adapters/as400_adapter.rb +2 -0
- data/lib/active_record/connection_adapters/db2_adapter.rb +1 -1
- data/lib/arel/visitors/db2.rb +5 -1
- data/lib/arel/visitors/hsqldb.rb +1 -0
- data/lib/arel/visitors/sql_server.rb +55 -13
- data/lib/arjdbc/db2/adapter.rb +197 -227
- data/lib/arjdbc/db2/as400.rb +124 -0
- data/lib/arjdbc/db2/connection_methods.rb +20 -1
- data/lib/arjdbc/derby/adapter.rb +17 -85
- data/lib/arjdbc/derby/connection_methods.rb +2 -1
- data/lib/arjdbc/discover.rb +55 -47
- data/lib/arjdbc/h2/adapter.rb +52 -18
- data/lib/arjdbc/h2/connection_methods.rb +10 -2
- data/lib/arjdbc/hsqldb/adapter.rb +33 -9
- data/lib/arjdbc/hsqldb/connection_methods.rb +10 -2
- data/lib/arjdbc/informix.rb +2 -1
- data/lib/arjdbc/jdbc.rb +5 -1
- data/lib/arjdbc/jdbc/adapter.rb +167 -89
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/adapter_require.rb +46 -0
- data/lib/arjdbc/jdbc/base_ext.rb +25 -3
- data/lib/arjdbc/jdbc/callbacks.rb +9 -8
- data/lib/arjdbc/jdbc/column.rb +8 -20
- data/lib/arjdbc/jdbc/connection.rb +69 -80
- data/lib/arjdbc/jdbc/extension.rb +6 -8
- data/lib/arjdbc/jdbc/jdbc.rake +3 -141
- data/lib/arjdbc/jdbc/rake_tasks.rb +3 -10
- data/lib/arjdbc/mssql/adapter.rb +108 -34
- data/lib/arjdbc/mssql/connection_methods.rb +3 -1
- data/lib/arjdbc/mssql/limit_helpers.rb +3 -2
- data/lib/arjdbc/mssql/lock_helpers.rb +5 -1
- data/lib/arjdbc/mysql/adapter.rb +127 -70
- data/lib/arjdbc/mysql/connection_methods.rb +5 -2
- data/lib/arjdbc/oracle/adapter.rb +124 -94
- data/lib/arjdbc/oracle/connection_methods.rb +2 -1
- data/lib/arjdbc/postgresql/adapter.rb +99 -67
- data/lib/arjdbc/postgresql/column_cast.rb +3 -5
- data/lib/arjdbc/postgresql/connection_methods.rb +6 -6
- data/lib/arjdbc/railtie.rb +3 -1
- data/lib/arjdbc/sqlite3/adapter.rb +60 -43
- data/lib/arjdbc/sqlite3/connection_methods.rb +9 -9
- data/lib/arjdbc/sybase.rb +1 -1
- data/lib/arjdbc/tasks.rb +13 -0
- data/lib/arjdbc/tasks/database_tasks.rb +50 -0
- data/lib/arjdbc/tasks/databases.rake +89 -0
- data/lib/arjdbc/tasks/databases3.rake +203 -0
- data/lib/arjdbc/tasks/databases4.rake +39 -0
- data/lib/arjdbc/tasks/db2_database_tasks.rb +104 -0
- data/lib/arjdbc/tasks/derby_database_tasks.rb +95 -0
- data/lib/arjdbc/tasks/h2_database_tasks.rb +29 -0
- data/lib/arjdbc/tasks/hsqldb_database_tasks.rb +70 -0
- data/lib/arjdbc/tasks/jdbc_database_tasks.rb +122 -0
- data/lib/arjdbc/tasks/mssql_database_tasks.rb +36 -0
- data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +297 -0
- data/lib/arjdbc/tasks/oracle_database_tasks.rb +62 -0
- data/lib/arjdbc/version.rb +1 -1
- data/pom.xml +11 -12
- data/rails_generators/jdbc_generator.rb +1 -1
- data/rails_generators/templates/config/initializers/jdbc.rb +8 -5
- data/rails_generators/templates/lib/tasks/jdbc.rake +7 -4
- data/rakelib/02-test.rake +42 -15
- data/rakelib/compile.rake +29 -2
- data/rakelib/db.rake +2 -1
- data/rakelib/rails.rake +23 -6
- data/src/java/arjdbc/ArJdbcModule.java +175 -0
- data/src/java/arjdbc/db2/DB2Module.java +2 -1
- data/src/java/arjdbc/derby/DerbyModule.java +5 -24
- data/src/java/arjdbc/hsqldb/HSQLDBModule.java +3 -2
- data/src/java/arjdbc/jdbc/AdapterJavaService.java +3 -46
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +1001 -259
- data/src/java/arjdbc/mssql/MSSQLModule.java +2 -1
- data/src/java/arjdbc/mysql/MySQLModule.java +4 -3
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +12 -7
- data/src/java/arjdbc/oracle/OracleModule.java +2 -1
- data/src/java/arjdbc/sqlite3/SQLite3Module.java +2 -1
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +12 -0
- data/test/db/db2.rb +14 -7
- data/test/db/db2/rake_test.rb +82 -0
- data/test/db/db2/rake_test_data.sql +35 -0
- data/test/db/db2/simple_test.rb +20 -0
- data/test/db/db2/unit_test.rb +3 -1
- data/test/db/derby.rb +7 -5
- data/test/db/derby/rake_test.rb +96 -0
- data/test/db/derby/simple_test.rb +10 -2
- data/test/db/h2.rb +6 -8
- data/test/db/h2/identity_column_test.rb +35 -0
- data/test/db/h2/offset_test.rb +49 -0
- data/test/db/h2/rake_test.rb +98 -0
- data/test/db/h2/schema_dump_test.rb +5 -1
- data/test/db/hsqldb.rb +6 -10
- data/test/db/hsqldb/rake_test.rb +101 -0
- data/test/db/hsqldb/schema_dump_test.rb +5 -1
- data/test/db/hsqldb/simple_test.rb +8 -0
- data/test/db/jndi_config.rb +1 -3
- data/test/db/jndi_pooled_config.rb +1 -3
- data/test/db/mssql/limit_offset_test.rb +23 -14
- data/test/db/mssql/rake_test.rb +143 -0
- data/test/db/mysql/_rails_test_mysql.32.out +1069 -1252
- data/test/db/mysql/nonstandard_primary_key_test.rb +21 -24
- data/test/db/mysql/rake_test.rb +97 -0
- data/test/db/mysql/schema_dump_test.rb +11 -11
- data/test/db/mysql/simple_test.rb +52 -3
- data/test/db/mysql/statement_escaping_test.rb +46 -0
- data/test/db/oracle/rake_test.rb +100 -0
- data/test/db/oracle/simple_test.rb +48 -0
- data/test/db/postgres/_rails_test_postgres.32.out +998 -1370
- data/test/db/postgres/active_schema_unit_test.rb +68 -0
- data/test/db/postgres/connection_test.rb +10 -2
- data/test/db/postgres/data_types_test.rb +2 -2
- data/test/db/postgres/ltree_test.rb +6 -5
- data/test/db/postgres/native_types_test.rb +1 -5
- data/test/db/postgres/rake_test.rb +117 -0
- data/test/db/postgres/schema_dump_test.rb +9 -2
- data/test/db/postgres/schema_test.rb +4 -2
- data/test/db/postgres/simple_test.rb +57 -16
- data/test/db/sqlite3.rb +3 -10
- data/test/db/sqlite3/_rails_test_sqlite3.32.out +1070 -1298
- data/test/db/sqlite3/rake_test.rb +71 -0
- data/test/db/sqlite3/simple_test.rb +9 -9
- data/test/has_many_through.rb +4 -1
- data/test/jdbc/db2.rb +14 -1
- data/test/jdbc_column_test.rb +23 -0
- data/test/{generic_jdbc_connection_test.rb → jdbc_connection_test.rb} +22 -17
- data/test/jndi_callbacks_test.rb +26 -28
- data/test/jndi_test.rb +7 -16
- data/test/models/data_types.rb +2 -1
- data/test/models/thing.rb +1 -0
- data/test/rails/mysql.rb +13 -0
- data/test/rails/sqlite3/version.rb +6 -0
- data/test/rails_stub.rb +31 -0
- data/test/rake_test_support.rb +298 -0
- data/test/serialize.rb +2 -4
- data/test/{helper.rb → shared_helper.rb} +0 -0
- data/test/simple.rb +167 -93
- data/test/test_helper.rb +52 -16
- metadata +388 -354
- data/lib/pg.rb +0 -26
- data/test/abstract_db_create.rb +0 -139
- data/test/activerecord/connection_adapters/type_conversion_test.rb +0 -36
- data/test/db/mssql/db_create_test.rb +0 -29
- data/test/db/mysql/db_create_test.rb +0 -33
- data/test/db/postgres/db_create_test.rb +0 -44
- data/test/db/postgres/db_drop_test.rb +0 -17
data/lib/arjdbc/h2/adapter.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
ArJdbc.load_java_part :H2
|
|
1
2
|
require 'arjdbc/hsqldb/adapter'
|
|
2
3
|
|
|
3
4
|
module ArJdbc
|
|
@@ -11,11 +12,11 @@ module ArJdbc
|
|
|
11
12
|
def self.column_selector
|
|
12
13
|
[ /\.h2\./i, lambda { |cfg, column| column.extend(::ArJdbc::H2::Column) } ]
|
|
13
14
|
end
|
|
14
|
-
|
|
15
|
+
|
|
15
16
|
module Column
|
|
16
|
-
|
|
17
|
+
|
|
17
18
|
private
|
|
18
|
-
|
|
19
|
+
|
|
19
20
|
def extract_limit(sql_type)
|
|
20
21
|
limit = super
|
|
21
22
|
case @sql_type = sql_type.downcase
|
|
@@ -34,14 +35,14 @@ module ArJdbc
|
|
|
34
35
|
when /blob|image|oid/i then @sql_type = 'blob'; limit = nil
|
|
35
36
|
when /clob|text/i then @sql_type = 'clob'; limit = nil
|
|
36
37
|
# NOTE: use lower-case due SchemaDumper not handling it's decimal/integer
|
|
37
|
-
# optimization case-insensitively due : column.type == :integer &&
|
|
38
|
+
# optimization case-insensitively due : column.type == :integer &&
|
|
38
39
|
# [/^numeric/, /^decimal/].any? { |e| e.match(column.sql_type) }
|
|
39
40
|
when /^decimal\(65535,32767\)/i
|
|
40
41
|
@sql_type = 'decimal'; nil
|
|
41
42
|
end
|
|
42
43
|
limit
|
|
43
44
|
end
|
|
44
|
-
|
|
45
|
+
|
|
45
46
|
def simplified_type(field_type)
|
|
46
47
|
case field_type
|
|
47
48
|
when /^bit|bool/i then :boolean
|
|
@@ -54,7 +55,7 @@ module ArJdbc
|
|
|
54
55
|
super
|
|
55
56
|
end
|
|
56
57
|
end
|
|
57
|
-
|
|
58
|
+
|
|
58
59
|
# Post process default value from JDBC into a Rails-friendly format (columns{-internal})
|
|
59
60
|
def default_value(value)
|
|
60
61
|
# H2 auto-generated key default value
|
|
@@ -63,11 +64,11 @@ module ArJdbc
|
|
|
63
64
|
return $1 if value =~ /^'(.*)'$/
|
|
64
65
|
value
|
|
65
66
|
end
|
|
66
|
-
|
|
67
|
+
|
|
67
68
|
end
|
|
68
|
-
|
|
69
|
+
|
|
69
70
|
ADAPTER_NAME = 'H2' # :nodoc:
|
|
70
|
-
|
|
71
|
+
|
|
71
72
|
def adapter_name # :nodoc:
|
|
72
73
|
ADAPTER_NAME
|
|
73
74
|
end
|
|
@@ -79,14 +80,14 @@ module ArJdbc
|
|
|
79
80
|
'jdbch2' => ::Arel::Visitors::HSQLDB,
|
|
80
81
|
})
|
|
81
82
|
end
|
|
82
|
-
|
|
83
|
+
|
|
83
84
|
# #deprecated
|
|
84
85
|
def h2_adapter # :nodoc:
|
|
85
86
|
true
|
|
86
87
|
end
|
|
87
88
|
|
|
88
89
|
NATIVE_DATABASE_TYPES = {
|
|
89
|
-
:primary_key => "
|
|
90
|
+
:primary_key => "bigint identity",
|
|
90
91
|
:boolean => { :name => "boolean" },
|
|
91
92
|
:tinyint => { :name => "tinyint", :limit => 1 },
|
|
92
93
|
:smallint => { :name => "smallint", :limit => 2 },
|
|
@@ -115,11 +116,11 @@ module ArJdbc
|
|
|
115
116
|
def native_database_types
|
|
116
117
|
NATIVE_DATABASE_TYPES.dup
|
|
117
118
|
end
|
|
118
|
-
|
|
119
|
+
|
|
119
120
|
def modify_types(types)
|
|
120
121
|
types
|
|
121
122
|
end
|
|
122
|
-
|
|
123
|
+
|
|
123
124
|
def type_to_sql(type, limit = nil, precision = nil, scale = nil)
|
|
124
125
|
case type.to_sym
|
|
125
126
|
when :integer
|
|
@@ -146,6 +147,10 @@ module ArJdbc
|
|
|
146
147
|
super
|
|
147
148
|
end
|
|
148
149
|
end
|
|
150
|
+
|
|
151
|
+
def empty_insert_statement_value
|
|
152
|
+
"VALUES ()"
|
|
153
|
+
end
|
|
149
154
|
|
|
150
155
|
def tables
|
|
151
156
|
@connection.tables(nil, h2_schema)
|
|
@@ -164,7 +169,7 @@ module ArJdbc
|
|
|
164
169
|
def current_schema
|
|
165
170
|
execute('CALL SCHEMA()')[0].values[0]
|
|
166
171
|
end
|
|
167
|
-
|
|
172
|
+
|
|
168
173
|
def quote(value, column = nil) # :nodoc:
|
|
169
174
|
case value
|
|
170
175
|
when String
|
|
@@ -177,9 +182,9 @@ module ArJdbc
|
|
|
177
182
|
super
|
|
178
183
|
end
|
|
179
184
|
end
|
|
180
|
-
|
|
185
|
+
|
|
181
186
|
# EXPLAIN support :
|
|
182
|
-
|
|
187
|
+
|
|
183
188
|
def supports_explain?; true; end
|
|
184
189
|
|
|
185
190
|
def explain(arel, binds = [])
|
|
@@ -188,8 +193,37 @@ module ArJdbc
|
|
|
188
193
|
raw_result[0].values.join("\n") # [ "SELECT \n ..." ].to_s
|
|
189
194
|
end
|
|
190
195
|
|
|
191
|
-
|
|
196
|
+
def structure_dump
|
|
197
|
+
execute('SCRIPT SIMPLE').map do |result|
|
|
198
|
+
# [ { 'script' => SQL }, { 'script' ... }, ... ]
|
|
199
|
+
case sql = result.first[1] # ['script']
|
|
200
|
+
when /CREATE USER IF NOT EXISTS SA/i then nil
|
|
201
|
+
else sql
|
|
202
|
+
end
|
|
203
|
+
end.compact.join("\n\n")
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def structure_load(dump)
|
|
207
|
+
dump.each_line("\n\n") { |ddl| execute(ddl) }
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def shutdown
|
|
211
|
+
execute 'SHUTDOWN COMPACT'
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def recreate_database(name = nil, options = {}) # :nodoc:
|
|
215
|
+
drop_database(name)
|
|
216
|
+
create_database(name, options)
|
|
217
|
+
end
|
|
192
218
|
|
|
219
|
+
def create_database(name = nil, options = {}); end # :nodoc:
|
|
220
|
+
|
|
221
|
+
def drop_database(name = nil) # :nodoc:
|
|
222
|
+
execute('DROP ALL OBJECTS')
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
private
|
|
226
|
+
|
|
193
227
|
def change_column_null(table_name, column_name, null, default = nil)
|
|
194
228
|
if !null && !default.nil?
|
|
195
229
|
execute("UPDATE #{table_name} SET #{column_name}=#{quote(default)} WHERE #{column_name} IS NULL")
|
|
@@ -204,6 +238,6 @@ module ArJdbc
|
|
|
204
238
|
def h2_schema
|
|
205
239
|
@config[:schema] || ''
|
|
206
240
|
end
|
|
207
|
-
|
|
241
|
+
|
|
208
242
|
end
|
|
209
243
|
end
|
|
@@ -6,9 +6,17 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
|
6
6
|
rescue LoadError # assuming driver.jar is on the class-path
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
config[:url] ||=
|
|
9
|
+
config[:url] ||= begin
|
|
10
|
+
db = config[:database]
|
|
11
|
+
if db[0, 4] == 'mem:' || db[0, 5] == 'file:' || db[0, 5] == 'hsql:'
|
|
12
|
+
"jdbc:h2:#{db}"
|
|
13
|
+
else
|
|
14
|
+
"jdbc:h2:file:#{db}"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
10
17
|
config[:driver] ||= defined?(::Jdbc::H2.driver_name) ? ::Jdbc::H2.driver_name : 'org.h2.Driver'
|
|
11
|
-
config[:adapter_spec]
|
|
18
|
+
config[:adapter_spec] ||= ::ArJdbc::H2
|
|
19
|
+
|
|
12
20
|
embedded_driver(config)
|
|
13
21
|
end
|
|
14
22
|
alias_method :jdbch2_connection, :h2_connection
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
ArJdbc.load_java_part :HSQLDB
|
|
1
2
|
require 'arjdbc/hsqldb/explain_support'
|
|
2
3
|
|
|
3
4
|
module ArJdbc
|
|
@@ -188,6 +189,12 @@ module ArJdbc
|
|
|
188
189
|
end
|
|
189
190
|
end
|
|
190
191
|
|
|
192
|
+
def empty_insert_statement_value
|
|
193
|
+
# on HSQLDB only work with tables that have a default value for each
|
|
194
|
+
# and every column ... you'll need to avoid `Model.create!` on 4.0
|
|
195
|
+
'DEFAULT VALUES'
|
|
196
|
+
end
|
|
197
|
+
|
|
191
198
|
# filter out system tables (that otherwise end up in db/schema.rb)
|
|
192
199
|
# JdbcConnection#tables
|
|
193
200
|
# now takes an optional block filter so we can screen out
|
|
@@ -201,19 +208,36 @@ module ArJdbc
|
|
|
201
208
|
def remove_index(table_name, options = {})
|
|
202
209
|
execute "DROP INDEX #{quote_column_name(index_name(table_name, options))}"
|
|
203
210
|
end
|
|
211
|
+
|
|
212
|
+
def structure_dump
|
|
213
|
+
execute('SCRIPT').map do |result|
|
|
214
|
+
# [ { 'command' => SQL }, { 'command' ... }, ... ]
|
|
215
|
+
case sql = result.first[1] # ['command']
|
|
216
|
+
when /CREATE USER SA PASSWORD DIGEST .*?/i then nil
|
|
217
|
+
when /CREATE SCHEMA PUBLIC AUTHORIZATION DBA/i then nil
|
|
218
|
+
when /GRANT DBA TO SA/i then nil
|
|
219
|
+
else sql
|
|
220
|
+
end
|
|
221
|
+
end.compact.join("\n\n")
|
|
222
|
+
end
|
|
204
223
|
|
|
205
|
-
def
|
|
206
|
-
|
|
224
|
+
def structure_load(dump)
|
|
225
|
+
dump.each_line("\n\n") { |ddl| execute(ddl) }
|
|
207
226
|
end
|
|
208
227
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
# avoiding method_missing error
|
|
212
|
-
def create_database(name)
|
|
228
|
+
def shutdown
|
|
229
|
+
execute 'SHUTDOWN'
|
|
213
230
|
end
|
|
214
|
-
|
|
215
|
-
def
|
|
216
|
-
|
|
231
|
+
|
|
232
|
+
def recreate_database(name = nil, options = {}) # :nodoc:
|
|
233
|
+
drop_database(name)
|
|
234
|
+
create_database(name, options)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def create_database(name = nil, options = {}); end # :nodoc:
|
|
238
|
+
|
|
239
|
+
def drop_database(name = nil) # :nodoc:
|
|
240
|
+
execute('DROP SCHEMA PUBLIC CASCADE')
|
|
217
241
|
end
|
|
218
242
|
|
|
219
243
|
end
|
|
@@ -6,10 +6,18 @@ ArJdbc::ConnectionMethods.module_eval do
|
|
|
6
6
|
rescue LoadError # assuming driver.jar is on the class-path
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
config[:url] ||=
|
|
9
|
+
config[:url] ||= begin
|
|
10
|
+
db = config[:database]
|
|
11
|
+
if db[0, 4] == 'mem:' || db[0, 5] == 'file:' || db[0, 5] == 'hsql:'
|
|
12
|
+
"jdbc:hsqldb:#{db}"
|
|
13
|
+
else
|
|
14
|
+
"jdbc:hsqldb:file:#{db}"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
10
17
|
config[:driver] ||= defined?(::Jdbc::HSQLDB.driver_name) ? ::Jdbc::HSQLDB.driver_name : 'org.hsqldb.jdbcDriver'
|
|
11
|
-
config[:adapter_spec]
|
|
18
|
+
config[:adapter_spec] ||= ::ArJdbc::HSQLDB
|
|
12
19
|
config[:connection_alive_sql] ||= 'CALL PI()' # does not like 'SELECT 1'
|
|
20
|
+
|
|
13
21
|
embedded_driver(config)
|
|
14
22
|
end
|
|
15
23
|
alias_method :jdbchsqldb_connection, :hsqldb_connection
|
data/lib/arjdbc/informix.rb
CHANGED
data/lib/arjdbc/jdbc.rb
CHANGED
data/lib/arjdbc/jdbc/adapter.rb
CHANGED
|
@@ -16,31 +16,42 @@ module ActiveRecord
|
|
|
16
16
|
module ConnectionAdapters
|
|
17
17
|
class JdbcAdapter < AbstractAdapter
|
|
18
18
|
extend ShadowCoreMethods
|
|
19
|
-
|
|
19
|
+
|
|
20
|
+
include JdbcConnectionPoolCallbacks
|
|
20
21
|
|
|
21
22
|
attr_reader :config
|
|
22
|
-
|
|
23
|
-
def initialize(connection, logger, config)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
config[:adapter_spec] ||= spec
|
|
27
|
-
unless connection
|
|
28
|
-
connection_class = jdbc_connection_class spec
|
|
29
|
-
connection = connection_class.new config
|
|
23
|
+
|
|
24
|
+
def initialize(connection, logger, config = nil) # (logger, config)
|
|
25
|
+
if config.nil? && logger.respond_to?(:key?) # only 2 arguments given
|
|
26
|
+
config, logger, connection = logger, connection, nil
|
|
30
27
|
end
|
|
28
|
+
|
|
29
|
+
@config = config
|
|
30
|
+
|
|
31
|
+
@config[:adapter_spec] = adapter_spec(@config) unless @config.key?(:adapter_spec)
|
|
32
|
+
spec = @config[:adapter_spec]
|
|
33
|
+
|
|
34
|
+
connection ||= jdbc_connection_class(spec).new(@config)
|
|
35
|
+
|
|
31
36
|
super(connection, logger)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
|
|
38
|
+
# kind of like `extend ArJdbc::MyDB if self.class == JdbcAdapter` :
|
|
39
|
+
klass = @config[:adapter_class]
|
|
40
|
+
extend spec if spec && ( ! klass || klass == JdbcAdapter)
|
|
41
|
+
|
|
42
|
+
connection.adapter = self # prepares native database types
|
|
43
|
+
|
|
44
|
+
# NOTE: should not be necessary for JNDI due reconnect! on checkout :
|
|
45
|
+
configure_connection if respond_to?(:configure_connection)
|
|
46
|
+
|
|
37
47
|
JndiConnectionPoolCallbacks.prepare(self, connection)
|
|
48
|
+
|
|
49
|
+
@visitor = new_visitor(@config) # nil if no AREL (AR-2.3)
|
|
38
50
|
end
|
|
39
|
-
|
|
51
|
+
|
|
40
52
|
def jdbc_connection_class(spec)
|
|
41
53
|
connection_class = spec.jdbc_connection_class if spec && spec.respond_to?(:jdbc_connection_class)
|
|
42
|
-
connection_class
|
|
43
|
-
connection_class
|
|
54
|
+
connection_class ? connection_class : ::ActiveRecord::ConnectionAdapters::JdbcConnection
|
|
44
55
|
end
|
|
45
56
|
|
|
46
57
|
def jdbc_column_class
|
|
@@ -67,18 +78,17 @@ module ActiveRecord
|
|
|
67
78
|
# Locate specialized adapter specification if one exists based on config data
|
|
68
79
|
def adapter_spec(config)
|
|
69
80
|
dialect = (config[:dialect] || config[:driver]).to_s
|
|
70
|
-
::ArJdbc.
|
|
71
|
-
constant = ::ArJdbc.const_get(constant) # e.g. ArJdbc::MySQL
|
|
72
|
-
|
|
81
|
+
::ArJdbc.modules.each do |constant| # e.g. ArJdbc::MySQL
|
|
73
82
|
if constant.respond_to?(:adapter_matcher)
|
|
74
83
|
spec = constant.adapter_matcher(dialect, config)
|
|
75
84
|
return spec if spec
|
|
76
85
|
end
|
|
77
86
|
end
|
|
78
87
|
|
|
79
|
-
if config[:jndi] && ! config[:dialect]
|
|
88
|
+
if (config[:jndi] || config[:data_source]) && ! config[:dialect]
|
|
80
89
|
begin
|
|
81
|
-
data_source =
|
|
90
|
+
data_source = config[:data_source] ||
|
|
91
|
+
Java::JavaxNaming::InitialContext.new.lookup(config[:jndi])
|
|
82
92
|
connection = data_source.getConnection
|
|
83
93
|
config[:dialect] = connection.getMetaData.getDatabaseProductName
|
|
84
94
|
rescue Java::JavaSql::SQLException => e
|
|
@@ -97,41 +107,99 @@ module ActiveRecord
|
|
|
97
107
|
types
|
|
98
108
|
end
|
|
99
109
|
|
|
100
|
-
def adapter_name
|
|
110
|
+
def adapter_name # :nodoc:
|
|
101
111
|
'JDBC'
|
|
102
112
|
end
|
|
103
113
|
|
|
114
|
+
def self.arel2_visitors(config)
|
|
115
|
+
{ 'jdbc' => ::Arel::Visitors::ToSql }
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# NOTE: called from {ConnectionPool#checkout} (up till AR-3.2)
|
|
104
119
|
def self.visitor_for(pool)
|
|
105
120
|
config = pool.spec.config
|
|
106
|
-
adapter = config[:adapter]
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
121
|
+
adapter = config[:adapter] # e.g. "sqlite3" (based on {#adapter_name})
|
|
122
|
+
unless visitor = ::Arel::Visitors::VISITORS[ adapter ]
|
|
123
|
+
adapter_spec = config[:adapter_spec] || self # e.g. ArJdbc::SQLite3
|
|
124
|
+
if adapter =~ /^(jdbc|jndi)$/
|
|
125
|
+
visitor = adapter_spec.arel2_visitors(config).values.first
|
|
126
|
+
else
|
|
127
|
+
visitor = adapter_spec.arel2_visitors(config)[adapter]
|
|
128
|
+
end
|
|
112
129
|
end
|
|
130
|
+
( prepared_statements?(config) ? visitor : bind_substitution(visitor) ).new(pool)
|
|
113
131
|
end
|
|
114
132
|
|
|
115
|
-
def self.
|
|
116
|
-
|
|
133
|
+
def self.configure_arel2_visitors(config)
|
|
134
|
+
visitors = ::Arel::Visitors::VISITORS
|
|
135
|
+
klass = config[:adapter_spec]
|
|
136
|
+
klass = self unless klass.respond_to?(:arel2_visitors)
|
|
137
|
+
visitor = nil
|
|
138
|
+
klass.arel2_visitors(config).each do |name, arel|
|
|
139
|
+
visitors[name] = ( visitor = arel )
|
|
140
|
+
end
|
|
141
|
+
if visitor && config[:adapter] =~ /^(jdbc|jndi)$/
|
|
142
|
+
visitors[ config[:adapter] ] = visitor
|
|
143
|
+
end
|
|
144
|
+
visitor
|
|
117
145
|
end
|
|
118
146
|
|
|
119
|
-
def
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
visitor =
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
visitor = v
|
|
126
|
-
visitors[k] = v
|
|
147
|
+
def new_visitor(config = self.config)
|
|
148
|
+
visitor = ::Arel::Visitors::VISITORS[ adapter = config[:adapter] ]
|
|
149
|
+
unless visitor
|
|
150
|
+
visitor = self.class.configure_arel2_visitors(config)
|
|
151
|
+
unless visitor
|
|
152
|
+
raise "no visitor configured for adapter: #{adapter.inspect}"
|
|
127
153
|
end
|
|
128
|
-
|
|
129
|
-
|
|
154
|
+
end
|
|
155
|
+
( prepared_statements? ? visitor : bind_substitution(visitor) ).new(self)
|
|
156
|
+
end
|
|
157
|
+
protected :new_visitor
|
|
158
|
+
|
|
159
|
+
unless defined? ::Arel::Visitors::VISITORS # NO-OP when no AREL (AR-2.3)
|
|
160
|
+
def self.configure_arel2_visitors(config); end
|
|
161
|
+
def new_visitor(config = self.config); end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
@@bind_substitutions = nil
|
|
165
|
+
|
|
166
|
+
# @return a {#Arel::Visitors::BindVisitor} class for given visitor type
|
|
167
|
+
def self.bind_substitution(visitor)
|
|
168
|
+
# NOTE: similar convention as in AR (but no base substitution type) :
|
|
169
|
+
# class BindSubstitution < ::Arel::Visitors::ToSql
|
|
170
|
+
# include ::Arel::Visitors::BindVisitor
|
|
171
|
+
# end
|
|
172
|
+
return const_get(:BindSubstitution) if const_defined?(:BindSubstitution)
|
|
173
|
+
|
|
174
|
+
@@bind_substitutions ||= Java::JavaUtil::HashMap.new
|
|
175
|
+
unless bind_visitor = @@bind_substitutions.get(visitor)
|
|
176
|
+
@@bind_substitutions.synchronized do
|
|
177
|
+
unless @@bind_substitutions.get(visitor)
|
|
178
|
+
bind_visitor = Class.new(visitor) do
|
|
179
|
+
include ::Arel::Visitors::BindVisitor
|
|
180
|
+
end
|
|
181
|
+
@@bind_substitutions.put(visitor, bind_visitor)
|
|
182
|
+
end
|
|
130
183
|
end
|
|
131
|
-
|
|
184
|
+
bind_visitor = @@bind_substitutions.get(visitor)
|
|
132
185
|
end
|
|
186
|
+
bind_visitor
|
|
133
187
|
end
|
|
134
|
-
|
|
188
|
+
|
|
189
|
+
begin
|
|
190
|
+
require 'arel/visitors/bind_visitor'
|
|
191
|
+
rescue LoadError # AR-3.0
|
|
192
|
+
def self.bind_substitution(visitor); visitor; end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def bind_substitution(visitor); self.class.bind_substitution(visitor); end
|
|
196
|
+
private :bind_substitution
|
|
197
|
+
|
|
198
|
+
# @override default implementation (does nothing silently)
|
|
199
|
+
def structure_dump
|
|
200
|
+
raise NotImplementedError, "structure_dump not supported"
|
|
201
|
+
end
|
|
202
|
+
|
|
135
203
|
def is_a?(klass) # :nodoc:
|
|
136
204
|
# This is to fake out current_adapter? conditional logic in AR tests
|
|
137
205
|
if Class === klass && klass.name =~ /#{adapter_name}Adapter$/i
|
|
@@ -145,11 +213,11 @@ module ActiveRecord
|
|
|
145
213
|
true
|
|
146
214
|
end
|
|
147
215
|
|
|
148
|
-
def native_database_types
|
|
216
|
+
def native_database_types # :nodoc:
|
|
149
217
|
@connection.native_database_types
|
|
150
218
|
end
|
|
151
219
|
|
|
152
|
-
def database_name
|
|
220
|
+
def database_name # :nodoc:
|
|
153
221
|
@connection.database_name
|
|
154
222
|
end
|
|
155
223
|
|
|
@@ -193,8 +261,7 @@ module ActiveRecord
|
|
|
193
261
|
end
|
|
194
262
|
|
|
195
263
|
def reconnect!
|
|
196
|
-
@connection.reconnect!
|
|
197
|
-
configure_connection if respond_to?(:configure_connection)
|
|
264
|
+
@connection.reconnect! # handles adapter.configure_connection
|
|
198
265
|
@connection
|
|
199
266
|
end
|
|
200
267
|
|
|
@@ -207,61 +274,71 @@ module ActiveRecord
|
|
|
207
274
|
def jdbc_insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = []) # :nodoc:
|
|
208
275
|
insert_sql(sql, name, pk, id_value, sequence_name, binds)
|
|
209
276
|
end
|
|
277
|
+
alias_chained_method :insert, :query_dirty, :jdbc_insert
|
|
210
278
|
|
|
211
279
|
def jdbc_update(sql, name = nil, binds = []) # :nodoc:
|
|
212
280
|
execute(sql, name, binds)
|
|
213
281
|
end
|
|
282
|
+
alias_chained_method :update, :query_dirty, :jdbc_update
|
|
214
283
|
|
|
215
284
|
def jdbc_select_all(sql, name = nil, binds = []) # :nodoc:
|
|
216
285
|
select(sql, name, binds)
|
|
217
286
|
end
|
|
218
|
-
|
|
219
|
-
# Allow query caching to work even when we override alias_method_chain'd methods
|
|
220
287
|
alias_chained_method :select_all, :query_cache, :jdbc_select_all
|
|
221
|
-
alias_chained_method :update, :query_dirty, :jdbc_update
|
|
222
|
-
alias_chained_method :insert, :query_dirty, :jdbc_insert
|
|
223
288
|
|
|
224
289
|
end
|
|
225
|
-
|
|
226
|
-
def
|
|
290
|
+
|
|
291
|
+
def columns(table_name, name = nil)
|
|
227
292
|
@connection.columns(table_name.to_s)
|
|
228
293
|
end
|
|
229
|
-
alias_chained_method :columns, :query_cache, :jdbc_columns
|
|
230
294
|
|
|
231
295
|
# Executes +sql+ statement in the context of this connection using
|
|
232
296
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
|
233
297
|
# the executed +sql+ statement.
|
|
234
298
|
def exec_query(sql, name = 'SQL', binds = []) # :nodoc:
|
|
235
|
-
|
|
299
|
+
sql = to_sql(sql, binds)
|
|
300
|
+
if prepared_statements?
|
|
301
|
+
log(sql, name, binds) { @connection.execute_query(sql, binds) }
|
|
302
|
+
else
|
|
303
|
+
sql = suble_binds(sql, binds)
|
|
304
|
+
log(sql, name) { @connection.execute_query(sql) }
|
|
305
|
+
end
|
|
236
306
|
end
|
|
237
307
|
|
|
238
308
|
# Executes insert +sql+ statement in the context of this connection using
|
|
239
309
|
# +binds+ as the bind substitutes. +name+ is the logged along with
|
|
240
310
|
# the executed +sql+ statement.
|
|
241
311
|
def exec_insert(sql, name, binds, pk = nil, sequence_name = nil) # :nodoc:
|
|
242
|
-
|
|
312
|
+
sql = suble_binds to_sql(sql, binds), binds
|
|
313
|
+
log(sql, name || 'SQL') { @connection.execute_insert(sql) }
|
|
243
314
|
end
|
|
244
315
|
|
|
245
316
|
# Executes delete +sql+ statement in the context of this connection using
|
|
246
317
|
# +binds+ as the bind substitutes. +name+ is the logged along with
|
|
247
318
|
# the executed +sql+ statement.
|
|
248
319
|
def exec_delete(sql, name, binds) # :nodoc:
|
|
249
|
-
|
|
320
|
+
sql = suble_binds to_sql(sql, binds), binds
|
|
321
|
+
log(sql, name || 'SQL') { @connection.execute_delete(sql) }
|
|
250
322
|
end
|
|
251
323
|
|
|
252
324
|
# Executes update +sql+ statement in the context of this connection using
|
|
253
325
|
# +binds+ as the bind substitutes. +name+ is the logged along with
|
|
254
326
|
# the executed +sql+ statement.
|
|
255
327
|
def exec_update(sql, name, binds) # :nodoc:
|
|
256
|
-
|
|
328
|
+
sql = suble_binds to_sql(sql, binds), binds
|
|
329
|
+
log(sql, name || 'SQL') { @connection.execute_update(sql) }
|
|
257
330
|
end
|
|
258
331
|
|
|
259
332
|
# Similar to {#exec_query} except it returns "raw" results in an array
|
|
260
333
|
# where each rows is a hash with keys as columns (just like Rails used to
|
|
261
334
|
# do up until 3.0) instead of wrapping them in a {#ActiveRecord::Result}.
|
|
262
335
|
def exec_query_raw(sql, name = 'SQL', binds = [], &block) # :nodoc:
|
|
263
|
-
|
|
264
|
-
|
|
336
|
+
sql = to_sql(sql, binds)
|
|
337
|
+
if prepared_statements?
|
|
338
|
+
log(sql, name, binds) { @connection.execute_query_raw(sql, binds, &block) }
|
|
339
|
+
else
|
|
340
|
+
sql = suble_binds(sql, binds)
|
|
341
|
+
log(sql, name) { @connection.execute_query_raw(sql, &block) }
|
|
265
342
|
end
|
|
266
343
|
end
|
|
267
344
|
|
|
@@ -289,7 +366,7 @@ module ActiveRecord
|
|
|
289
366
|
|
|
290
367
|
# Executes the SQL statement in the context of this connection.
|
|
291
368
|
def execute(sql, name = nil, binds = [])
|
|
292
|
-
sql = to_sql(sql, binds)
|
|
369
|
+
sql = suble_binds to_sql(sql, binds), binds
|
|
293
370
|
if name == :skip_logging
|
|
294
371
|
_execute(sql, name)
|
|
295
372
|
else
|
|
@@ -304,7 +381,7 @@ module ActiveRecord
|
|
|
304
381
|
|
|
305
382
|
# Executes the SQL statement in the context of this connection.
|
|
306
383
|
def execute(sql, name = nil, binds = [])
|
|
307
|
-
sql = to_sql(sql, binds)
|
|
384
|
+
sql = suble_binds to_sql(sql, binds), binds
|
|
308
385
|
if name == :skip_logging
|
|
309
386
|
_execute(sql, name)
|
|
310
387
|
else
|
|
@@ -386,37 +463,28 @@ module ActiveRecord
|
|
|
386
463
|
if ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR == 0
|
|
387
464
|
|
|
388
465
|
#attr_reader :visitor unless method_defined?(:visitor) # not in 3.0
|
|
389
|
-
|
|
466
|
+
|
|
390
467
|
# Converts an AREL AST to SQL.
|
|
391
468
|
def to_sql(arel, binds = [])
|
|
392
|
-
# NOTE: can not handle `visitor.accept(arel.ast)` right
|
|
393
|
-
|
|
394
|
-
sql = arel.respond_to?(:to_sql) ? arel.send(:to_sql) : arel
|
|
395
|
-
return sql if binds.blank?
|
|
396
|
-
sql.gsub('?') { quote(*binds.shift.reverse) }
|
|
469
|
+
# NOTE: can not handle `visitor.accept(arel.ast)` right
|
|
470
|
+
arel.respond_to?(:to_sql) ? arel.send(:to_sql) : arel
|
|
397
471
|
end
|
|
398
472
|
|
|
399
473
|
elsif ActiveRecord::VERSION::MAJOR >= 3 # AR >= 3.1 or 4.0
|
|
400
|
-
|
|
474
|
+
|
|
401
475
|
# Converts an AREL AST to SQL.
|
|
402
476
|
def to_sql(arel, binds = [])
|
|
403
477
|
if arel.respond_to?(:ast)
|
|
404
478
|
visitor.accept(arel.ast) { quote(*binds.shift.reverse) }
|
|
405
|
-
else
|
|
406
|
-
|
|
407
|
-
return sql if binds.blank?
|
|
408
|
-
sql.gsub('?') { quote(*binds.shift.reverse) }
|
|
479
|
+
else
|
|
480
|
+
arel
|
|
409
481
|
end
|
|
410
482
|
end
|
|
411
483
|
|
|
412
484
|
else # AR-2.3 no #to_sql method
|
|
413
485
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
sql = sql.send(:to_sql) if sql.respond_to?(:to_sql)
|
|
417
|
-
return sql if binds.blank?
|
|
418
|
-
copy = binds.dup
|
|
419
|
-
sql.gsub('?') { quote(*copy.shift.reverse) }
|
|
486
|
+
def to_sql(sql, binds = nil)
|
|
487
|
+
sql
|
|
420
488
|
end
|
|
421
489
|
|
|
422
490
|
end
|
|
@@ -467,18 +535,28 @@ module ActiveRecord
|
|
|
467
535
|
|
|
468
536
|
private
|
|
469
537
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
538
|
+
def prepared_statements?
|
|
539
|
+
self.class.prepared_statements?(config)
|
|
540
|
+
end
|
|
541
|
+
|
|
542
|
+
def self.prepared_statements?(config)
|
|
543
|
+
config.key?(:prepared_statements) ?
|
|
544
|
+
type_cast_config_to_boolean(config.fetch(:prepared_statements)) :
|
|
545
|
+
false # NOTE: off by default for now
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
def suble_binds(sql, binds)
|
|
549
|
+
return sql if binds.nil? || binds.empty?
|
|
550
|
+
copy = binds.dup
|
|
551
|
+
sql.gsub('?') { quote(*copy.shift.reverse) }
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
# @deprecated replaced with {#suble_binds}
|
|
555
|
+
def substitute_binds(sql, binds)
|
|
556
|
+
suble_binds(extract_sql(sql), binds)
|
|
479
557
|
end
|
|
480
558
|
|
|
481
|
-
#
|
|
559
|
+
# @deprecated no longer used
|
|
482
560
|
def extract_sql(obj)
|
|
483
561
|
obj.respond_to?(:to_sql) ? obj.send(:to_sql) : obj
|
|
484
562
|
end
|