kb-activerecord-jdbc-adapter 0.9.7.1-java → 1.0.0.beta1-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.
- data/History.txt +11 -0
- data/Manifest.txt +71 -38
- data/lib/active_record/connection_adapters/cachedb_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/derby_adapter.rb +1 -13
- data/lib/active_record/connection_adapters/h2_adapter.rb +1 -13
- data/lib/active_record/connection_adapters/hsqldb_adapter.rb +1 -13
- data/lib/active_record/connection_adapters/informix_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/jdbc_adapter.rb +1 -661
- data/lib/active_record/connection_adapters/jndi_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/mssql_adapter.rb +1 -13
- data/lib/active_record/connection_adapters/mysql_adapter.rb +1 -13
- data/lib/active_record/connection_adapters/oracle_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -13
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -13
- data/lib/activerecord-jdbc-adapter.rb +2 -2
- data/lib/arjdbc/cachedb/adapter.rb +20 -0
- data/lib/arjdbc/cachedb/connection_methods.rb +10 -0
- data/lib/arjdbc/cachedb.rb +3 -0
- data/lib/{jdbc_adapter/jdbc_db2.rb → arjdbc/db2/adapter.rb} +2 -17
- data/lib/arjdbc/db2.rb +2 -0
- data/lib/{jdbc_adapter/jdbc_derby.rb → arjdbc/derby/adapter.rb} +8 -26
- data/lib/arjdbc/derby/connection_methods.rb +18 -0
- data/lib/arjdbc/derby.rb +7 -0
- data/lib/arjdbc/discover.rb +99 -0
- data/lib/{jdbc_adapter/jdbc_firebird.rb → arjdbc/firebird/adapter.rb} +12 -16
- data/lib/arjdbc/firebird.rb +2 -0
- data/lib/arjdbc/h2/adapter.rb +15 -0
- data/lib/arjdbc/h2/connection_methods.rb +12 -0
- data/lib/arjdbc/h2.rb +4 -0
- data/lib/{jdbc_adapter/jdbc_hsqldb.rb → arjdbc/hsqldb/adapter.rb} +6 -58
- data/lib/arjdbc/hsqldb/connection_methods.rb +14 -0
- data/lib/arjdbc/hsqldb.rb +4 -0
- data/lib/{jdbc_adapter/jdbc_informix.rb → arjdbc/informix/adapter.rb} +6 -19
- data/lib/arjdbc/informix/connection_methods.rb +10 -0
- data/lib/arjdbc/informix.rb +3 -0
- data/lib/arjdbc/jdbc/adapter.rb +235 -0
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/callbacks.rb +44 -0
- data/lib/arjdbc/jdbc/column.rb +38 -0
- data/lib/arjdbc/jdbc/compatibility.rb +51 -0
- data/lib/arjdbc/jdbc/connection.rb +97 -0
- data/lib/arjdbc/jdbc/connection_methods.rb +16 -0
- data/lib/arjdbc/jdbc/core_ext.rb +24 -0
- data/lib/arjdbc/jdbc/discover.rb +18 -0
- data/lib/arjdbc/jdbc/driver.rb +44 -0
- data/lib/arjdbc/jdbc/extension.rb +47 -0
- data/lib/arjdbc/jdbc/java.rb +14 -0
- data/lib/{jdbc_adapter → arjdbc/jdbc}/missing_functionality_helper.rb +5 -5
- data/lib/arjdbc/jdbc/quoted_primary_key.rb +28 -0
- data/lib/{jdbc_adapter → arjdbc/jdbc}/railtie.rb +1 -1
- data/lib/arjdbc/jdbc/require_driver.rb +16 -0
- data/lib/arjdbc/jdbc/type_converter.rb +119 -0
- data/lib/arjdbc/jdbc.rb +2 -0
- data/lib/{jdbc_adapter/jdbc_mimer.rb → arjdbc/mimer/adapter.rb} +16 -19
- data/lib/arjdbc/mimer.rb +2 -0
- data/lib/{jdbc_adapter/jdbc_mssql.rb → arjdbc/mssql/adapter.rb} +19 -31
- data/lib/arjdbc/mssql/connection_methods.rb +13 -0
- data/lib/arjdbc/mssql.rb +4 -0
- data/lib/arjdbc/mysql/adapter.rb +388 -0
- data/lib/arjdbc/mysql/connection_methods.rb +26 -0
- data/lib/arjdbc/mysql.rb +4 -0
- data/lib/{jdbc_adapter/jdbc_oracle.rb → arjdbc/oracle/adapter.rb} +9 -17
- data/lib/arjdbc/oracle/connection_methods.rb +11 -0
- data/lib/arjdbc/oracle.rb +3 -0
- data/lib/{jdbc_adapter/jdbc_postgre.rb → arjdbc/postgresql/adapter.rb} +7 -36
- data/lib/arjdbc/postgresql/connection_methods.rb +21 -0
- data/lib/arjdbc/postgresql.rb +4 -0
- data/lib/{jdbc_adapter/jdbc_sqlite3.rb → arjdbc/sqlite3/adapter.rb} +106 -104
- data/lib/arjdbc/sqlite3/connection_methods.rb +33 -0
- data/lib/arjdbc/sqlite3.rb +4 -0
- data/lib/arjdbc/sybase/adapter.rb +46 -0
- data/lib/arjdbc/sybase.rb +2 -0
- data/lib/arjdbc/version.rb +8 -0
- data/lib/arjdbc.rb +29 -0
- data/lib/jdbc_adapter/version.rb +3 -5
- data/lib/jdbc_adapter.rb +2 -27
- data/rails_generators/templates/config/initializers/jdbc.rb +1 -1
- data/rakelib/compile.rake +3 -2
- data/rakelib/package.rake +3 -3
- data/src/java/{jdbc_adapter/JdbcDerbySpec.java → arjdbc/derby/DerbyModule.java} +32 -32
- data/src/java/{jdbc_adapter/JdbcAdapterInternalService.java → arjdbc/jdbc/AdapterJavaService.java} +13 -7
- data/src/java/{jdbc_adapter → arjdbc/jdbc}/JdbcConnectionFactory.java +6 -6
- data/src/java/{jdbc_adapter → arjdbc/jdbc}/RubyJdbcConnection.java +91 -16
- data/src/java/arjdbc/jdbc/SQLBlock.java +48 -0
- data/src/java/{jdbc_adapter → arjdbc/mssql}/MssqlRubyJdbcConnection.java +5 -2
- data/src/java/{jdbc_adapter/JdbcMySQLSpec.java → arjdbc/mysql/MySQLModule.java} +12 -12
- data/src/java/{jdbc_adapter/PostgresRubyJdbcConnection.java → arjdbc/postgresql/PostgresqlRubyJdbcConnection.java} +11 -9
- data/src/java/arjdbc/sqlite3/Sqlite3RubyJdbcConnection.java +64 -0
- data/test/abstract_db_create.rb +4 -1
- data/test/activerecord/connection_adapters/type_conversion_test.rb +1 -1
- data/test/db/cachedb.rb +0 -0
- data/test/db/derby.rb +12 -14
- data/test/db/hsqldb.rb +3 -2
- data/test/db/jndi_config.rb +4 -4
- data/test/db/sqlite3.rb +2 -6
- data/test/db2_simple_test.rb +23 -0
- data/test/derby_migration_test.rb +50 -3
- data/test/jdbc_common.rb +1 -1
- data/test/jndi_callbacks_test.rb +1 -0
- data/test/postgres_nonseq_pkey_test.rb +0 -2
- data/test/postgres_schema_search_path_test.rb +0 -2
- data/test/simple.rb +3 -3
- data/test/sybase_jtds_simple_test.rb +22 -0
- metadata +81 -46
- data/lib/active_record/connection_adapters/jdbc_adapter_spec.rb +0 -26
- data/lib/jdbc_adapter/jdbc_adapter_internal.jar +0 -0
- data/lib/jdbc_adapter/jdbc_cachedb.rb +0 -33
- data/lib/jdbc_adapter/jdbc_mysql.rb +0 -260
- data/lib/jdbc_adapter/jdbc_sybase.rb +0 -50
- data/src/java/jdbc_adapter/SQLBlock.java +0 -27
- data/src/java/jdbc_adapter/Sqlite3RubyJdbcConnection.java +0 -41
- data/test/jdbc_adapter/jdbc_db2_test.rb +0 -26
- data/test/jdbc_adapter/jdbc_sybase_test.rb +0 -33
- data/test/minirunit/testConnect.rb +0 -14
- data/test/minirunit/testH2.rb +0 -73
- data/test/minirunit/testHsqldb.rb +0 -73
- data/test/minirunit/testLoadActiveRecord.rb +0 -3
- data/test/minirunit/testMysql.rb +0 -83
- data/test/minirunit/testRawSelect.rb +0 -24
- data/test/minirunit.rb +0 -109
- /data/lib/{jdbc_adapter → arjdbc/jdbc}/jdbc.rake +0 -0
- /data/lib/{jdbc_adapter → arjdbc/jdbc}/rake_tasks.rb +0 -0
- /data/lib/{jdbc_adapter → arjdbc/mssql}/tsql_helper.rb +0 -0
@@ -0,0 +1,235 @@
|
|
1
|
+
require 'active_record/version'
|
2
|
+
require 'active_record/connection_adapters/abstract_adapter'
|
3
|
+
require 'arjdbc/version'
|
4
|
+
require 'arjdbc/jdbc/require_driver'
|
5
|
+
require 'arjdbc/jdbc/connection_methods'
|
6
|
+
require 'arjdbc/jdbc/compatibility'
|
7
|
+
require 'arjdbc/jdbc/core_ext'
|
8
|
+
require 'arjdbc/jdbc/java'
|
9
|
+
require 'arjdbc/jdbc/type_converter'
|
10
|
+
require 'arjdbc/jdbc/driver'
|
11
|
+
require 'arjdbc/jdbc/column'
|
12
|
+
require 'arjdbc/jdbc/connection'
|
13
|
+
require 'arjdbc/jdbc/callbacks'
|
14
|
+
require 'arjdbc/jdbc/extension'
|
15
|
+
require 'bigdecimal'
|
16
|
+
|
17
|
+
module ActiveRecord
|
18
|
+
module ConnectionAdapters
|
19
|
+
class JdbcAdapter < AbstractAdapter
|
20
|
+
extend ShadowCoreMethods
|
21
|
+
include CompatibilityMethods if CompatibilityMethods.needed?(self)
|
22
|
+
include JdbcConnectionPoolCallbacks if JdbcConnectionPoolCallbacks.needed?
|
23
|
+
|
24
|
+
attr_reader :config
|
25
|
+
|
26
|
+
def initialize(connection, logger, config)
|
27
|
+
@config = config
|
28
|
+
spec = adapter_spec config
|
29
|
+
unless connection
|
30
|
+
connection_class = jdbc_connection_class spec
|
31
|
+
connection = connection_class.new config
|
32
|
+
end
|
33
|
+
super(connection, logger)
|
34
|
+
extend spec if spec
|
35
|
+
connection.adapter = self
|
36
|
+
JndiConnectionPoolCallbacks.prepare(self, connection)
|
37
|
+
end
|
38
|
+
|
39
|
+
def jdbc_connection_class(spec)
|
40
|
+
connection_class = spec.jdbc_connection_class if spec && spec.respond_to?(:jdbc_connection_class)
|
41
|
+
connection_class = ::ActiveRecord::ConnectionAdapters::JdbcConnection unless connection_class
|
42
|
+
connection_class
|
43
|
+
end
|
44
|
+
|
45
|
+
def jdbc_column_class
|
46
|
+
ActiveRecord::ConnectionAdapters::JdbcColumn
|
47
|
+
end
|
48
|
+
|
49
|
+
# Locate specialized adapter specification if one exists based on config data
|
50
|
+
def adapter_spec(config)
|
51
|
+
dialect = (config[:dialect] || config[:driver]).to_s
|
52
|
+
::ArJdbc.constants.map { |name| ::ArJdbc.const_get name }.each do |constant|
|
53
|
+
if constant.respond_to? :adapter_matcher
|
54
|
+
spec = constant.adapter_matcher(dialect, config)
|
55
|
+
return spec if spec
|
56
|
+
end
|
57
|
+
end
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
|
61
|
+
def modify_types(tp)
|
62
|
+
tp
|
63
|
+
end
|
64
|
+
|
65
|
+
def adapter_name #:nodoc:
|
66
|
+
'JDBC'
|
67
|
+
end
|
68
|
+
|
69
|
+
def is_a?(klass) # :nodoc:
|
70
|
+
# This is to fake out current_adapter? conditional logic in AR tests
|
71
|
+
if Class === klass && klass.name =~ /#{adapter_name}Adapter$/i
|
72
|
+
true
|
73
|
+
else
|
74
|
+
super
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def supports_migrations?
|
79
|
+
true
|
80
|
+
end
|
81
|
+
|
82
|
+
def native_database_types #:nodoc:
|
83
|
+
@connection.native_database_types
|
84
|
+
end
|
85
|
+
|
86
|
+
def database_name #:nodoc:
|
87
|
+
@connection.database_name
|
88
|
+
end
|
89
|
+
|
90
|
+
def native_sql_to_type(tp)
|
91
|
+
if /^(.*?)\(([0-9]+)\)/ =~ tp
|
92
|
+
tname = $1
|
93
|
+
limit = $2.to_i
|
94
|
+
ntype = native_database_types
|
95
|
+
if ntype[:primary_key] == tp
|
96
|
+
return :primary_key,nil
|
97
|
+
else
|
98
|
+
ntype.each do |name,val|
|
99
|
+
if name == :primary_key
|
100
|
+
next
|
101
|
+
end
|
102
|
+
if val[:name].downcase == tname.downcase && (val[:limit].nil? || val[:limit].to_i == limit)
|
103
|
+
return name,limit
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
elsif /^(.*?)/ =~ tp
|
108
|
+
tname = $1
|
109
|
+
ntype = native_database_types
|
110
|
+
if ntype[:primary_key] == tp
|
111
|
+
return :primary_key,nil
|
112
|
+
else
|
113
|
+
ntype.each do |name,val|
|
114
|
+
if val[:name].downcase == tname.downcase && val[:limit].nil?
|
115
|
+
return name,nil
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
else
|
120
|
+
return :string,255
|
121
|
+
end
|
122
|
+
return nil,nil
|
123
|
+
end
|
124
|
+
|
125
|
+
def active?
|
126
|
+
@connection.active?
|
127
|
+
end
|
128
|
+
|
129
|
+
def reconnect!
|
130
|
+
@connection.reconnect!
|
131
|
+
@connection
|
132
|
+
end
|
133
|
+
|
134
|
+
def disconnect!
|
135
|
+
@connection.disconnect!
|
136
|
+
end
|
137
|
+
|
138
|
+
def execute(sql, name = nil)
|
139
|
+
if name == :skip_logging
|
140
|
+
_execute(sql)
|
141
|
+
else
|
142
|
+
log(sql, name) { _execute(sql) }
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# we need to do it this way, to allow Rails stupid tests to always work
|
147
|
+
# even if we define a new execute method. Instead of mixing in a new
|
148
|
+
# execute, an _execute should be mixed in.
|
149
|
+
def _execute(sql, name = nil)
|
150
|
+
@connection.execute(sql)
|
151
|
+
end
|
152
|
+
|
153
|
+
def jdbc_insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
|
154
|
+
insert_sql(sql, name, pk, id_value, sequence_name)
|
155
|
+
end
|
156
|
+
|
157
|
+
def jdbc_update(sql, name = nil) #:nodoc:
|
158
|
+
execute(sql, name)
|
159
|
+
end
|
160
|
+
def jdbc_select_all(sql, name = nil)
|
161
|
+
select(sql, name)
|
162
|
+
end
|
163
|
+
|
164
|
+
if ActiveRecord::VERSION::MAJOR < 3
|
165
|
+
# Allow query caching to work even when we override alias_method_chain'd methods
|
166
|
+
alias_chained_method :select_all, :query_cache, :jdbc_select_all
|
167
|
+
alias_chained_method :update, :query_dirty, :jdbc_update
|
168
|
+
alias_chained_method :insert, :query_dirty, :jdbc_insert
|
169
|
+
|
170
|
+
# Do we need this? Not in AR 3.
|
171
|
+
def select_one(sql, name = nil)
|
172
|
+
select(sql, name).first
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def select_rows(sql, name = nil)
|
177
|
+
rows = []
|
178
|
+
select(sql, name).each {|row| rows << row.values }
|
179
|
+
rows
|
180
|
+
end
|
181
|
+
|
182
|
+
def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
|
183
|
+
id = execute(sql, name = nil)
|
184
|
+
id_value || id
|
185
|
+
end
|
186
|
+
|
187
|
+
|
188
|
+
def jdbc_columns(table_name, name = nil)
|
189
|
+
@connection.columns(table_name.to_s)
|
190
|
+
end
|
191
|
+
alias_chained_method :columns, :query_cache, :jdbc_columns
|
192
|
+
|
193
|
+
def tables(name = nil)
|
194
|
+
@connection.tables
|
195
|
+
end
|
196
|
+
|
197
|
+
def indexes(table_name, name = nil, schema_name = nil)
|
198
|
+
@connection.indexes(table_name, name, schema_name)
|
199
|
+
end
|
200
|
+
|
201
|
+
def begin_db_transaction
|
202
|
+
@connection.begin
|
203
|
+
end
|
204
|
+
|
205
|
+
def commit_db_transaction
|
206
|
+
@connection.commit
|
207
|
+
end
|
208
|
+
|
209
|
+
def rollback_db_transaction
|
210
|
+
@connection.rollback
|
211
|
+
end
|
212
|
+
|
213
|
+
def write_large_object(*args)
|
214
|
+
@connection.write_large_object(*args)
|
215
|
+
end
|
216
|
+
|
217
|
+
def pk_and_sequence_for(table)
|
218
|
+
key = primary_key(table)
|
219
|
+
[key, nil] if key
|
220
|
+
end
|
221
|
+
|
222
|
+
def primary_key(table)
|
223
|
+
primary_keys(table).first
|
224
|
+
end
|
225
|
+
|
226
|
+
def primary_keys(table)
|
227
|
+
@connection.primary_keys(table)
|
228
|
+
end
|
229
|
+
|
230
|
+
def select(*args)
|
231
|
+
execute(*args)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
Binary file
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module JdbcConnectionPoolCallbacks
|
4
|
+
def self.included(base)
|
5
|
+
if base.respond_to?(:set_callback) # Rails 3 callbacks
|
6
|
+
base.set_callback :checkin, :after, :on_checkin
|
7
|
+
base.set_callback :checkout, :before, :on_checkout
|
8
|
+
else
|
9
|
+
base.checkin :on_checkin
|
10
|
+
base.checkout :on_checkout
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.needed?
|
15
|
+
ActiveRecord::Base.respond_to?(:connection_pool)
|
16
|
+
end
|
17
|
+
|
18
|
+
def on_checkin
|
19
|
+
# default implementation does nothing
|
20
|
+
end
|
21
|
+
|
22
|
+
def on_checkout
|
23
|
+
# default implementation does nothing
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module JndiConnectionPoolCallbacks
|
28
|
+
def self.prepare(adapter, conn)
|
29
|
+
if ActiveRecord::Base.respond_to?(:connection_pool) && conn.jndi_connection?
|
30
|
+
adapter.extend self
|
31
|
+
conn.disconnect! # disconnect initial connection in JdbcConnection#initialize
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def on_checkin
|
36
|
+
disconnect!
|
37
|
+
end
|
38
|
+
|
39
|
+
def on_checkout
|
40
|
+
reconnect!
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
class JdbcColumn < Column
|
4
|
+
attr_writer :limit, :precision
|
5
|
+
|
6
|
+
def initialize(config, name, default, *args)
|
7
|
+
call_discovered_column_callbacks(config)
|
8
|
+
super(name,default_value(default),*args)
|
9
|
+
init_column(name, default, *args)
|
10
|
+
end
|
11
|
+
|
12
|
+
def init_column(*args)
|
13
|
+
end
|
14
|
+
|
15
|
+
def default_value(val)
|
16
|
+
val
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.column_types
|
20
|
+
@column_types ||= ::ArJdbc.constants.map{|c|
|
21
|
+
::ArJdbc.const_get c }.select{ |c|
|
22
|
+
c.respond_to? :column_selector }.map{|c|
|
23
|
+
c.column_selector }.inject({}) { |h,val|
|
24
|
+
h[val[0]] = val[1]; h }
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
def call_discovered_column_callbacks(config)
|
29
|
+
dialect = config[:dialect] || config[:driver]
|
30
|
+
for reg, func in JdbcColumn.column_types
|
31
|
+
if reg === dialect.to_s
|
32
|
+
func.call(config,self)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# AR's 2.2 version of this method is sufficient, but we need it for
|
2
|
+
# older versions
|
3
|
+
if ActiveRecord::VERSION::MAJOR <= 2 && ActiveRecord::VERSION::MINOR < 2
|
4
|
+
module ActiveRecord
|
5
|
+
module ConnectionAdapters # :nodoc:
|
6
|
+
module SchemaStatements
|
7
|
+
# Convert the speficied column type to a SQL string.
|
8
|
+
def type_to_sql(type, limit = nil, precision = nil, scale = nil)
|
9
|
+
if native = native_database_types[type]
|
10
|
+
column_type_sql = (native.is_a?(Hash) ? native[:name] : native).dup
|
11
|
+
|
12
|
+
if type == :decimal # ignore limit, use precision and scale
|
13
|
+
scale ||= native[:scale]
|
14
|
+
|
15
|
+
if precision ||= native[:precision]
|
16
|
+
if scale
|
17
|
+
column_type_sql << "(#{precision},#{scale})"
|
18
|
+
else
|
19
|
+
column_type_sql << "(#{precision})"
|
20
|
+
end
|
21
|
+
elsif scale
|
22
|
+
raise ArgumentError, "Error adding decimal column: precision cannot be empty if scale if specified"
|
23
|
+
end
|
24
|
+
|
25
|
+
elsif limit ||= native.is_a?(Hash) && native[:limit]
|
26
|
+
column_type_sql << "(#{limit})"
|
27
|
+
end
|
28
|
+
|
29
|
+
column_type_sql
|
30
|
+
else
|
31
|
+
type
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
module ActiveRecord
|
40
|
+
module ConnectionAdapters
|
41
|
+
module CompatibilityMethods
|
42
|
+
def self.needed?(base)
|
43
|
+
!base.instance_methods.include?("quote_table_name")
|
44
|
+
end
|
45
|
+
|
46
|
+
def quote_table_name(name)
|
47
|
+
quote_column_name(name)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
class JdbcConnection
|
4
|
+
attr_reader :adapter, :connection_factory
|
5
|
+
|
6
|
+
# @native_database_types - setup properly by adapter= versus set_native_database_types.
|
7
|
+
# This contains type information for the adapter. Individual adapters can make tweaks
|
8
|
+
# by defined modify_types
|
9
|
+
#
|
10
|
+
# @native_types - This is the default type settings sans any modifications by the
|
11
|
+
# individual adapter. My guess is that if we loaded two adapters of different types
|
12
|
+
# then this is used as a base to be tweaked by each adapter to create @native_database_types
|
13
|
+
|
14
|
+
def initialize(config)
|
15
|
+
@config = config.symbolize_keys!
|
16
|
+
@config[:retry_count] ||= 5
|
17
|
+
@config[:connection_alive_sql] ||= "select 1"
|
18
|
+
@jndi_connection = false
|
19
|
+
@connection = nil
|
20
|
+
if @config[:jndi]
|
21
|
+
begin
|
22
|
+
configure_jndi
|
23
|
+
rescue => e
|
24
|
+
warn "JNDI data source unavailable: #{e.message}; trying straight JDBC"
|
25
|
+
configure_jdbc
|
26
|
+
end
|
27
|
+
else
|
28
|
+
configure_jdbc
|
29
|
+
end
|
30
|
+
connection # force the connection to load
|
31
|
+
set_native_database_types
|
32
|
+
@stmts = {}
|
33
|
+
rescue Exception => e
|
34
|
+
raise "The driver encountered an error: #{e}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def adapter=(adapter)
|
38
|
+
@adapter = adapter
|
39
|
+
@native_database_types = dup_native_types
|
40
|
+
@adapter.modify_types(@native_database_types)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Duplicate all native types into new hash structure so it can be modified
|
44
|
+
# without destroying original structure.
|
45
|
+
def dup_native_types
|
46
|
+
types = {}
|
47
|
+
@native_types.each_pair do |k, v|
|
48
|
+
types[k] = v.inject({}) do |memo, kv|
|
49
|
+
memo[kv.first] = begin kv.last.dup rescue kv.last end
|
50
|
+
memo
|
51
|
+
end
|
52
|
+
end
|
53
|
+
types
|
54
|
+
end
|
55
|
+
private :dup_native_types
|
56
|
+
|
57
|
+
def jndi_connection?
|
58
|
+
@jndi_connection
|
59
|
+
end
|
60
|
+
|
61
|
+
def active?
|
62
|
+
@connection
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
def configure_jndi
|
67
|
+
jndi = @config[:jndi].to_s
|
68
|
+
ctx = javax.naming.InitialContext.new
|
69
|
+
ds = ctx.lookup(jndi)
|
70
|
+
@connection_factory = JdbcConnectionFactory.impl do
|
71
|
+
ds.connection
|
72
|
+
end
|
73
|
+
unless @config[:driver]
|
74
|
+
@config[:driver] = connection.meta_data.connection.java_class.name
|
75
|
+
end
|
76
|
+
@jndi_connection = true
|
77
|
+
end
|
78
|
+
|
79
|
+
def configure_jdbc
|
80
|
+
driver = @config[:driver].to_s
|
81
|
+
user = @config[:username].to_s
|
82
|
+
pass = @config[:password].to_s
|
83
|
+
url = @config[:url].to_s
|
84
|
+
|
85
|
+
unless driver && url
|
86
|
+
raise ::ActiveRecord::ConnectionFailed, "jdbc adapter requires driver class and url"
|
87
|
+
end
|
88
|
+
|
89
|
+
jdbc_driver = JdbcDriver.new(driver)
|
90
|
+
jdbc_driver.load
|
91
|
+
@connection_factory = JdbcConnectionFactory.impl do
|
92
|
+
jdbc_driver.connection(url, user, pass)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class ActiveRecord::Base
|
2
|
+
class << self
|
3
|
+
def jdbc_connection(config)
|
4
|
+
adapter_class = config[:adapter_class]
|
5
|
+
adapter_class ||= ::ActiveRecord::ConnectionAdapters::JdbcAdapter
|
6
|
+
adapter_class.new(nil, logger, config)
|
7
|
+
end
|
8
|
+
alias jndi_connection jdbc_connection
|
9
|
+
|
10
|
+
def embedded_driver(config)
|
11
|
+
config[:username] ||= "sa"
|
12
|
+
config[:password] ||= ""
|
13
|
+
jdbc_connection(config)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module ActiveRecord # :nodoc:
|
2
|
+
# Represents exceptions that have propagated up through the JDBC API.
|
3
|
+
class JDBCError < ActiveRecordError
|
4
|
+
# The vendor code or error number that came from the database
|
5
|
+
attr_accessor :errno
|
6
|
+
|
7
|
+
# The full Java SQLException object that was raised
|
8
|
+
attr_accessor :sql_exception
|
9
|
+
end
|
10
|
+
|
11
|
+
module ConnectionAdapters # :nodoc:
|
12
|
+
# Allows properly re-wrapping/re-defining methods that may already
|
13
|
+
# be alias_method_chain'd.
|
14
|
+
module ShadowCoreMethods
|
15
|
+
def alias_chained_method(meth, feature, target)
|
16
|
+
if instance_methods.include?("#{meth}_without_#{feature}")
|
17
|
+
alias_method "#{meth}_without_#{feature}".to_sym, target
|
18
|
+
else
|
19
|
+
alias_method meth, target if meth != target
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module ArJdbc
|
2
|
+
def self.discover_extensions
|
3
|
+
if defined?(::Gem)
|
4
|
+
files = Gem.find_files('arjdbc/discover')
|
5
|
+
else
|
6
|
+
files = $LOAD_PATH.map do |p|
|
7
|
+
discover = File.join(p, 'arjdbc','discover.rb')
|
8
|
+
File.exist?(p) ? discover : nil
|
9
|
+
end.compact
|
10
|
+
end
|
11
|
+
files.each do |f|
|
12
|
+
puts "Loading #{f}" if $DEBUG
|
13
|
+
require f
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
discover_extensions
|
18
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
class JdbcDriver
|
4
|
+
def initialize(name)
|
5
|
+
@name = name
|
6
|
+
end
|
7
|
+
|
8
|
+
def driver_class
|
9
|
+
@driver_class ||= begin
|
10
|
+
driver_class_const = (@name[0...1].capitalize + @name[1..@name.length]).gsub(/\./, '_')
|
11
|
+
Jdbc::Mutex.synchronized do
|
12
|
+
unless Jdbc.const_defined?(driver_class_const)
|
13
|
+
driver_class_name = @name
|
14
|
+
Jdbc.module_eval do
|
15
|
+
include_class(driver_class_name) { driver_class_const }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
driver_class = Jdbc.const_get(driver_class_const)
|
20
|
+
raise "You specify a driver for your JDBC connection" unless driver_class
|
21
|
+
driver_class
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def load
|
26
|
+
Jdbc::DriverManager.registerDriver(create)
|
27
|
+
end
|
28
|
+
|
29
|
+
def connection(url, user, pass)
|
30
|
+
Jdbc::DriverManager.getConnection(url, user, pass)
|
31
|
+
rescue
|
32
|
+
# bypass DriverManager to get around problem with dynamically loaded jdbc drivers
|
33
|
+
props = java.util.Properties.new
|
34
|
+
props.setProperty("user", user)
|
35
|
+
props.setProperty("password", pass)
|
36
|
+
create.connect(url, props)
|
37
|
+
end
|
38
|
+
|
39
|
+
def create
|
40
|
+
driver_class.new
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module ArJdbc
|
2
|
+
# Defines an AR-JDBC extension. An extension consists of a
|
3
|
+
# declaration using this method and an ArJdbc::XYZ module that
|
4
|
+
# contains implementation and overrides for methods in
|
5
|
+
# ActiveRecord::ConnectionAdapters::AbstractAdapter. When you
|
6
|
+
# declare your extension, you provide a block that detects when a
|
7
|
+
# database configured to use the extension is present and loads the
|
8
|
+
# necessary code for it. AR-JDBC will patch the code into the base
|
9
|
+
# ActiveRecord::ConnectionAdapters::JdbcAdapter by extending an
|
10
|
+
# instance of it with your extension module.
|
11
|
+
#
|
12
|
+
# +name+ should be a symbol that is the name of a module to be
|
13
|
+
# defined under the +ArJdbc+ module.
|
14
|
+
#
|
15
|
+
# +block+ should be a one- or two-arity block that receives the
|
16
|
+
# dialect name or driver class name as the first argument, and
|
17
|
+
# optionally the whole database configuration hash as a second
|
18
|
+
# argument.
|
19
|
+
#
|
20
|
+
# Example:
|
21
|
+
#
|
22
|
+
# ArJdbc.extension :Frob do |name|
|
23
|
+
# if name =~ /frob/i
|
24
|
+
# # arjdbc/frob.rb should contain the implementation
|
25
|
+
# require 'arjdbc/frob'
|
26
|
+
# true
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
def self.extension(name,&block)
|
30
|
+
if const_defined?(name)
|
31
|
+
mod = const_get(name)
|
32
|
+
else
|
33
|
+
mod = const_set(name, Module.new)
|
34
|
+
end
|
35
|
+
(class << mod; self; end).instance_eval do
|
36
|
+
unless respond_to?(:adapter_matcher)
|
37
|
+
define_method :adapter_matcher do |name, config|
|
38
|
+
if block.arity == 1
|
39
|
+
block.call(name) ? mod : false
|
40
|
+
else
|
41
|
+
block.call(name, config) ? mod : false
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'java'
|
2
|
+
require 'arjdbc/jdbc/adapter_java'
|
3
|
+
|
4
|
+
module ActiveRecord
|
5
|
+
module ConnectionAdapters
|
6
|
+
module Jdbc
|
7
|
+
Mutex = java.lang.Object.new
|
8
|
+
DriverManager = java.sql.DriverManager
|
9
|
+
Types = java.sql.Types
|
10
|
+
end
|
11
|
+
|
12
|
+
java_import "arjdbc.jdbc.JdbcConnectionFactory"
|
13
|
+
end
|
14
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
module
|
1
|
+
module ArJdbc
|
2
2
|
module MissingFunctionalityHelper
|
3
3
|
#Taken from SQLite adapter
|
4
4
|
|
@@ -15,7 +15,7 @@ module JdbcSpec
|
|
15
15
|
move_table(altered_table_name, table_name, &caller)
|
16
16
|
end
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def move_table(from, to, options = {}, &block) #:nodoc:
|
20
20
|
copy_table(from, to, options, &block)
|
21
21
|
drop_table(from)
|
@@ -30,7 +30,7 @@ module JdbcSpec
|
|
30
30
|
(options[:rename][column.name] ||
|
31
31
|
options[:rename][column.name.to_sym] ||
|
32
32
|
column.name) : column.name
|
33
|
-
|
33
|
+
|
34
34
|
@definition.column(column_name, column.type,
|
35
35
|
:limit => column.limit, :default => column.default,
|
36
36
|
:null => column.null)
|
@@ -44,7 +44,7 @@ module JdbcSpec
|
|
44
44
|
@definition.columns.map {|column| column.name},
|
45
45
|
options[:rename] || {})
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
def copy_table_indexes(from, to, rename = {}) #:nodoc:
|
49
49
|
indexes(from).each do |index|
|
50
50
|
name = index.name.downcase
|
@@ -67,7 +67,7 @@ module JdbcSpec
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
end
|
70
|
-
|
70
|
+
|
71
71
|
def copy_table_contents(from, to, columns, rename = {}) #:nodoc:
|
72
72
|
column_mappings = Hash[*columns.map {|name| [name, name]}.flatten]
|
73
73
|
rename.inject(column_mappings) {|map, a| map[a.last] = a.first; map}
|