activerecord-jdbc-adapter 1.2.0 → 1.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +5 -0
- data/Gemfile.lock +1 -1
- data/History.txt +10 -0
- data/Rakefile +5 -5
- data/lib/arel/visitors/firebird.rb +10 -3
- data/lib/arjdbc/derby/adapter.rb +0 -1
- data/lib/arjdbc/h2/adapter.rb +17 -0
- data/lib/arjdbc/hsqldb/adapter.rb +1 -2
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/type_converter.rb +2 -2
- data/lib/arjdbc/mysql/adapter.rb +34 -43
- data/lib/arjdbc/postgresql/adapter.rb +35 -1
- data/lib/arjdbc/postgresql/connection_methods.rb +1 -0
- data/lib/arjdbc/sqlite3/adapter.rb +2 -2
- data/lib/arjdbc/version.rb +1 -1
- data/rakelib/bundler_ext.rb +11 -0
- data/rakelib/compile.rake +20 -22
- data/rakelib/db.rake +21 -13
- data/rakelib/rails.rake +1 -1
- data/src/java/arjdbc/derby/DerbyModule.java +69 -67
- data/src/java/arjdbc/sqlite3/Sqlite3RubyJdbcConnection.java +62 -0
- data/test/db/mysql.rb +3 -3
- data/test/db/postgres.rb +3 -3
- data/test/h2_change_column_test.rb +68 -0
- data/test/helper.rb +69 -0
- data/test/mysql_simple_test.rb +16 -4
- data/test/postgres_native_type_mapping_test.rb +6 -1
- data/test/postgres_simple_test.rb +12 -6
- data/test/postgres_type_conversion_test.rb +34 -0
- data/test/simple.rb +78 -6
- data/test/sqlite3_simple_test.rb +25 -3
- metadata +8 -2
data/Gemfile.lock
CHANGED
data/History.txt
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
== 1.2.1 (11/23/11)
|
2
|
+
|
3
|
+
- #117: Skip ? substitution when no bind parameters are given
|
4
|
+
- #115: Work around bug in ResultSetMetaData in SQLite
|
5
|
+
- Enhance the 'change_column' in H2 adapter to support additional options
|
6
|
+
- Deal with changes in RubyBigDecimal in trunk
|
7
|
+
- Decimal with scale zero handling (George Murphy)
|
8
|
+
- Fix blob handling for SQLite3 since SQLiteJDBC does not support
|
9
|
+
getBinary (Jean-Dominique Morani)
|
10
|
+
|
1
11
|
== 1.2.0 (09/13/11)
|
2
12
|
|
3
13
|
- Support for Rails 3.1
|
data/Rakefile
CHANGED
@@ -6,11 +6,11 @@ require 'bundler'
|
|
6
6
|
Bundler::GemHelper.install_tasks
|
7
7
|
require 'bundler/setup'
|
8
8
|
|
9
|
-
task :default => [:
|
9
|
+
task :default => [:jar, :test]
|
10
10
|
|
11
11
|
#ugh, bundler doesn't use tasks, so gotta hook up to both tasks.
|
12
|
-
task :build => :
|
13
|
-
task :install => :
|
12
|
+
task :build => :jar
|
13
|
+
task :install => :jar
|
14
14
|
|
15
15
|
ADAPTERS = %w[derby h2 hsqldb mssql mysql postgresql sqlite3].map {|a| "activerecord-jdbc#{a}-adapter" }
|
16
16
|
DRIVERS = %w[derby h2 hsqldb jtds mysql postgres sqlite3].map {|a| "jdbc-#{a}" }
|
@@ -44,13 +44,13 @@ end
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
desc "
|
47
|
+
desc "Release all adapters"
|
48
48
|
task "all:release" => ["release", *ADAPTERS.map { |f| "#{f}:release" }]
|
49
49
|
|
50
50
|
desc "Install all adapters"
|
51
51
|
task "all:install" => ["install", *ADAPTERS.map { |f| "#{f}:install" }]
|
52
52
|
|
53
|
-
desc "
|
53
|
+
desc "Build all adapters"
|
54
54
|
task "all:build" => ["build", *ADAPTERS.map { |f| "#{f}:build" }]
|
55
55
|
|
56
56
|
task :filelist do
|
@@ -4,12 +4,19 @@ module Arel
|
|
4
4
|
module Visitors
|
5
5
|
class Firebird < Arel::Visitors::ToSql
|
6
6
|
def visit_Arel_Nodes_SelectStatement o
|
7
|
-
[
|
7
|
+
lim_off = [
|
8
|
+
("FIRST #{visit(o.limit.expr)}" if o.limit),
|
9
|
+
("SKIP #{visit(o.offset.expr)}" if o.offset)
|
10
|
+
].compact.join(' ').strip
|
11
|
+
|
12
|
+
sql = [
|
8
13
|
o.cores.map { |x| visit_Arel_Nodes_SelectCore x }.join,
|
9
14
|
("ORDER BY #{o.orders.map { |x| visit x }.join(', ')}" unless o.orders.empty?),
|
10
|
-
("ROWS #{limit_for(o.limit)} " if o.limit),
|
11
|
-
("TO #{o.offset} " if o.offset),
|
12
15
|
].compact.join ' '
|
16
|
+
|
17
|
+
sql.sub!(/\A(\s*SELECT\s)/i, '\&' + lim_off + ' ') unless lim_off.empty?
|
18
|
+
|
19
|
+
sql
|
13
20
|
end
|
14
21
|
|
15
22
|
end
|
data/lib/arjdbc/derby/adapter.rb
CHANGED
data/lib/arjdbc/h2/adapter.rb
CHANGED
@@ -29,7 +29,24 @@ module ArJdbc
|
|
29
29
|
@connection.columns_internal(table_name.to_s, name, h2_schema)
|
30
30
|
end
|
31
31
|
|
32
|
+
def change_column(table_name, column_name, type, options = {}) #:nodoc:
|
33
|
+
execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} #{type_to_sql(type, options[:limit])}"
|
34
|
+
change_column_default(table_name, column_name, options[:default]) if options_include_default?(options)
|
35
|
+
change_column_null(table_name, column_name, options[:null], options[:default]) if options.key?(:null)
|
36
|
+
end
|
37
|
+
|
32
38
|
private
|
39
|
+
def change_column_null(table_name, column_name, null, default = nil)
|
40
|
+
if !null && !default.nil?
|
41
|
+
execute("UPDATE #{table_name} SET #{column_name}=#{quote(default)} WHERE #{column_name} IS NULL")
|
42
|
+
end
|
43
|
+
if null
|
44
|
+
execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET NULL"
|
45
|
+
else
|
46
|
+
execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET NOT NULL"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
33
50
|
def h2_schema
|
34
51
|
@config[:schema] || ''
|
35
52
|
end
|
@@ -11,7 +11,6 @@ module ::ArJdbc
|
|
11
11
|
when /longvarchar/i then :text
|
12
12
|
when /tinyint/i then :boolean
|
13
13
|
when /real/i then :float
|
14
|
-
when /decimal/i then :decimal
|
15
14
|
else
|
16
15
|
super
|
17
16
|
end
|
@@ -71,7 +70,7 @@ module ::ArJdbc
|
|
71
70
|
if respond_to?(:h2_adapter) && value.empty?
|
72
71
|
"''"
|
73
72
|
elsif column && column.type == :binary
|
74
|
-
"'#{value.unpack("H*")}'"
|
73
|
+
"'#{value.unpack("H*")[0]}'"
|
75
74
|
elsif column && (column.type == :integer ||
|
76
75
|
column.respond_to?(:primary) && column.primary && column.klass != String)
|
77
76
|
value.to_i.to_s
|
Binary file
|
@@ -34,7 +34,7 @@ module ActiveRecord
|
|
34
34
|
lambda {|r| r['type_name'] =~ /^number$/i},
|
35
35
|
lambda {|r| r['type_name'] =~ /^real$/i},
|
36
36
|
lambda {|r| r['precision'] == '38'},
|
37
|
-
lambda {|r| r['data_type'] ==
|
37
|
+
lambda {|r| r['data_type'].to_i == Jdbc::Types::DECIMAL}],
|
38
38
|
:float => [ lambda {|r| [Jdbc::Types::FLOAT,Jdbc::Types::DOUBLE, Jdbc::Types::REAL].include?(r['data_type'].to_i)},
|
39
39
|
lambda {|r| r['data_type'].to_i == Jdbc::Types::REAL}, #Prefer REAL to DOUBLE for Postgresql
|
40
40
|
lambda {|r| r['type_name'] =~ /^float/i},
|
@@ -67,7 +67,7 @@ module ActiveRecord
|
|
67
67
|
lambda {|r| r['type_name'] =~ /^binary$/i}, ],
|
68
68
|
:boolean => [ lambda {|r| [Jdbc::Types::TINYINT].include?(r['data_type'].to_i)},
|
69
69
|
lambda {|r| r['type_name'] =~ /^bool/i},
|
70
|
-
lambda {|r| r['data_type'] ==
|
70
|
+
lambda {|r| r['data_type'].to_i == Jdbc::Types::BIT},
|
71
71
|
lambda {|r| r['type_name'] =~ /^tinyint$/i},
|
72
72
|
lambda {|r| r['type_name'] =~ /^decimal$/i},
|
73
73
|
lambda {|r| r['type_name'] =~ /^integer$/i}]
|
data/lib/arjdbc/mysql/adapter.rb
CHANGED
@@ -3,7 +3,7 @@ require 'active_record/connection_adapters/abstract/schema_definitions'
|
|
3
3
|
module ::ArJdbc
|
4
4
|
module MySQL
|
5
5
|
def self.column_selector
|
6
|
-
[/mysql/i, lambda {|cfg,col| col.extend(::ArJdbc::MySQL::
|
6
|
+
[/mysql/i, lambda {|cfg,col| col.extend(::ArJdbc::MySQL::ColumnExtensions)}]
|
7
7
|
end
|
8
8
|
|
9
9
|
def self.extended(adapter)
|
@@ -18,7 +18,7 @@ module ::ArJdbc
|
|
18
18
|
::ActiveRecord::ConnectionAdapters::MySQLJdbcConnection
|
19
19
|
end
|
20
20
|
|
21
|
-
module
|
21
|
+
module ColumnExtensions
|
22
22
|
def extract_default(default)
|
23
23
|
if sql_type =~ /blob/i || type == :text
|
24
24
|
if default.blank?
|
@@ -42,7 +42,7 @@ module ::ArJdbc
|
|
42
42
|
case field_type
|
43
43
|
when /tinyint\(1\)|bit/i then :boolean
|
44
44
|
when /enum/i then :string
|
45
|
-
when /
|
45
|
+
when /year/i then :integer
|
46
46
|
else
|
47
47
|
super
|
48
48
|
end
|
@@ -61,6 +61,7 @@ module ::ArJdbc
|
|
61
61
|
else
|
62
62
|
nil # we could return 65535 here, but we leave it undecorated by default
|
63
63
|
end
|
64
|
+
when /^enum/i; 255
|
64
65
|
when /^bigint/i; 8
|
65
66
|
when /^int/i; 4
|
66
67
|
when /^mediumint/i; 3
|
@@ -131,30 +132,16 @@ module ::ArJdbc
|
|
131
132
|
end
|
132
133
|
end
|
133
134
|
|
135
|
+
def quote_column_name(name)
|
136
|
+
"`#{name.to_s.gsub('`', '``')}`"
|
137
|
+
end
|
138
|
+
|
134
139
|
def quoted_true
|
135
|
-
|
140
|
+
"1"
|
136
141
|
end
|
137
142
|
|
138
143
|
def quoted_false
|
139
|
-
|
140
|
-
end
|
141
|
-
|
142
|
-
def begin_db_transaction #:nodoc:
|
143
|
-
@connection.begin
|
144
|
-
rescue Exception
|
145
|
-
# Transactions aren't supported
|
146
|
-
end
|
147
|
-
|
148
|
-
def commit_db_transaction #:nodoc:
|
149
|
-
@connection.commit
|
150
|
-
rescue Exception
|
151
|
-
# Transactions aren't supported
|
152
|
-
end
|
153
|
-
|
154
|
-
def rollback_db_transaction #:nodoc:
|
155
|
-
@connection.rollback
|
156
|
-
rescue Exception
|
157
|
-
# Transactions aren't supported
|
144
|
+
"0"
|
158
145
|
end
|
159
146
|
|
160
147
|
def supports_savepoints? #:nodoc:
|
@@ -208,7 +195,7 @@ module ::ArJdbc
|
|
208
195
|
def jdbc_columns(table_name, name = nil)#:nodoc:
|
209
196
|
sql = "SHOW FIELDS FROM #{quote_table_name(table_name)}"
|
210
197
|
execute(sql, :skip_logging).map do |field|
|
211
|
-
::ActiveRecord::ConnectionAdapters::
|
198
|
+
::ActiveRecord::ConnectionAdapters::MysqlAdapter::Column.new(field["Field"], field["Default"], field["Type"], field["Null"] == "YES")
|
212
199
|
end
|
213
200
|
end
|
214
201
|
|
@@ -308,8 +295,8 @@ module ::ArJdbc
|
|
308
295
|
|
309
296
|
def show_variable(var)
|
310
297
|
res = execute("show variables like '#{var}'")
|
311
|
-
|
312
|
-
|
298
|
+
result_row = res.detect {|row| row["Variable_name"] == var }
|
299
|
+
result_row && result_row["Value"]
|
313
300
|
end
|
314
301
|
|
315
302
|
def charset
|
@@ -391,21 +378,6 @@ module ActiveRecord::ConnectionAdapters
|
|
391
378
|
remove_const(:MysqlColumn) if const_defined?(:MysqlColumn)
|
392
379
|
remove_const(:MysqlAdapter) if const_defined?(:MysqlAdapter)
|
393
380
|
|
394
|
-
class MysqlColumn < JdbcColumn
|
395
|
-
include ArJdbc::MySQL::Column
|
396
|
-
|
397
|
-
def initialize(name, *args)
|
398
|
-
if Hash === name
|
399
|
-
super
|
400
|
-
else
|
401
|
-
super(nil, name, *args)
|
402
|
-
end
|
403
|
-
end
|
404
|
-
|
405
|
-
def call_discovered_column_callbacks(*)
|
406
|
-
end
|
407
|
-
end
|
408
|
-
|
409
381
|
class MysqlAdapter < JdbcAdapter
|
410
382
|
include ArJdbc::MySQL
|
411
383
|
|
@@ -419,17 +391,36 @@ module ActiveRecord::ConnectionAdapters
|
|
419
391
|
end
|
420
392
|
|
421
393
|
def jdbc_column_class
|
422
|
-
ActiveRecord::ConnectionAdapters::
|
394
|
+
ActiveRecord::ConnectionAdapters::MysqlAdapter::Column
|
423
395
|
end
|
424
396
|
|
425
397
|
alias_chained_method :columns, :query_cache, :jdbc_columns
|
426
398
|
|
399
|
+
remove_const(:Column) if const_defined?(:Column)
|
400
|
+
class Column < JdbcColumn
|
401
|
+
include ArJdbc::MySQL::ColumnExtensions
|
402
|
+
|
403
|
+
def initialize(name, *args)
|
404
|
+
if Hash === name
|
405
|
+
super
|
406
|
+
else
|
407
|
+
super(nil, name, *args)
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
def call_discovered_column_callbacks(*)
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
427
415
|
protected
|
428
416
|
def exec_insert(sql, name, binds)
|
429
417
|
binds = binds.dup
|
430
418
|
|
431
419
|
# Pretend to support bind parameters
|
432
|
-
|
420
|
+
unless binds.empty?
|
421
|
+
sql = sql.gsub('?') { quote(*binds.shift.reverse) }
|
422
|
+
end
|
423
|
+
execute sql, name
|
433
424
|
end
|
434
425
|
alias :exec_update :exec_insert
|
435
426
|
alias :exec_delete :exec_insert
|
@@ -44,6 +44,7 @@ module ::ArJdbc
|
|
44
44
|
return :integer if field_type =~ /^(big|)serial/i
|
45
45
|
return :string if field_type =~ /\[\]$/i || field_type =~ /^interval/i
|
46
46
|
return :string if field_type =~ /^(?:point|lseg|box|"?path"?|polygon|circle)/i
|
47
|
+
return :string if field_type =~ /^uuid/i
|
47
48
|
return :datetime if field_type =~ /^timestamp/i
|
48
49
|
return :float if field_type =~ /^(?:real|double precision)$/i
|
49
50
|
return :binary if field_type =~ /^bytea/i
|
@@ -494,7 +495,7 @@ module ::ArJdbc
|
|
494
495
|
end
|
495
496
|
|
496
497
|
def quote_column_name(name)
|
497
|
-
%("#{name}")
|
498
|
+
%("#{name.to_s.gsub("\"", "\"\"")}")
|
498
499
|
end
|
499
500
|
|
500
501
|
def quoted_date(value) #:nodoc:
|
@@ -615,3 +616,36 @@ module ::ArJdbc
|
|
615
616
|
end
|
616
617
|
end
|
617
618
|
|
619
|
+
module ActiveRecord::ConnectionAdapters
|
620
|
+
remove_const(:PostgreSQLAdapter) if const_defined?(:PostgreSQLAdapter)
|
621
|
+
|
622
|
+
class PostgreSQLColumn < JdbcColumn
|
623
|
+
include ArJdbc::PostgreSQL::Column
|
624
|
+
|
625
|
+
def initialize(name, *args)
|
626
|
+
if Hash === name
|
627
|
+
super
|
628
|
+
else
|
629
|
+
super(nil, name, *args)
|
630
|
+
end
|
631
|
+
end
|
632
|
+
|
633
|
+
def call_discovered_column_callbacks(*)
|
634
|
+
end
|
635
|
+
end
|
636
|
+
|
637
|
+
class PostgreSQLAdapter < JdbcAdapter
|
638
|
+
include ArJdbc::PostgreSQL
|
639
|
+
|
640
|
+
def jdbc_connection_class(spec)
|
641
|
+
::ArJdbc::PostgreSQL.jdbc_connection_class
|
642
|
+
end
|
643
|
+
|
644
|
+
def jdbc_column_class
|
645
|
+
ActiveRecord::ConnectionAdapters::PostgreSQLColumn
|
646
|
+
end
|
647
|
+
|
648
|
+
alias_chained_method :insert, :query_dirty, :pg_insert
|
649
|
+
alias_chained_method :columns, :query_cache, :pg_columns
|
650
|
+
end
|
651
|
+
end
|
@@ -10,6 +10,7 @@ class ActiveRecord::Base
|
|
10
10
|
config[:url] ||= "jdbc:postgresql://#{config[:host]}:#{config[:port]}/#{config[:database]}"
|
11
11
|
config[:url] << config[:pg_params] if config[:pg_params]
|
12
12
|
config[:driver] ||= "org.postgresql.Driver"
|
13
|
+
config[:adapter_class] = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
|
13
14
|
config[:adapter_spec] = ::ArJdbc::PostgreSQL
|
14
15
|
conn = jdbc_connection(config)
|
15
16
|
conn.execute("SET SEARCH_PATH TO #{config[:schema_search_path]}") if config[:schema_search_path]
|
@@ -120,7 +120,7 @@ module ::ArJdbc
|
|
120
120
|
end
|
121
121
|
|
122
122
|
def quote_column_name(name) #:nodoc:
|
123
|
-
%Q("#{name}")
|
123
|
+
%Q("#{name.to_s.gsub('"', '""')}")
|
124
124
|
end
|
125
125
|
|
126
126
|
def quote_string(str)
|
@@ -152,7 +152,7 @@ module ::ArJdbc
|
|
152
152
|
end
|
153
153
|
|
154
154
|
def last_insert_id
|
155
|
-
|
155
|
+
@connection.last_insert_row_id
|
156
156
|
end
|
157
157
|
|
158
158
|
def tables(name = nil) #:nodoc:
|
data/lib/arjdbc/version.rb
CHANGED
data/rakelib/compile.rake
CHANGED
@@ -1,25 +1,23 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
rescue => e
|
7
|
-
end
|
8
|
-
unless jruby_cpath
|
9
|
-
jruby_cpath = ENV['JRUBY_PARENT_CLASSPATH'] || ENV['JRUBY_HOME'] &&
|
10
|
-
FileList["#{ENV['JRUBY_HOME']}/lib/*.jar"].join(File::PATH_SEPARATOR)
|
11
|
-
end
|
12
|
-
jruby_cpath ? "-cp \"#{jruby_cpath}\"" : ""
|
13
|
-
end
|
1
|
+
jar_file = File.join(*%w(lib arjdbc jdbc adapter_java.jar))
|
2
|
+
begin
|
3
|
+
require 'ant'
|
4
|
+
directory "pkg/classes"
|
5
|
+
CLEAN << "pkg"
|
14
6
|
|
15
|
-
|
7
|
+
file jar_file => FileList['src/java/**/*.java', 'pkg/classes'] do
|
8
|
+
rm_rf FileList['pkg/classes/**/*']
|
9
|
+
ant.javac :srcdir => "src/java", :destdir => "pkg/classes",
|
10
|
+
:source => "1.5", :target => "1.5", :debug => true,
|
11
|
+
:classpath => "${java.class.path}:${sun.boot.class.path}",
|
12
|
+
:includeantRuntime => false
|
16
13
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
14
|
+
ant.jar :basedir => "pkg/classes", :destfile => jar_file, :includes => "**/*.class"
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Compile the native Java code."
|
18
|
+
task :jar => jar_file
|
19
|
+
rescue LoadError
|
20
|
+
task :jar do
|
21
|
+
puts "Run 'jar' with JRuby to re-compile the agent extension class"
|
22
|
+
end
|
24
23
|
end
|
25
|
-
file jar_name => :java_compile
|