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.
@@ -0,0 +1,5 @@
1
+ rvm:
2
+ - jruby
3
+ branches:
4
+ only:
5
+ - master
@@ -24,7 +24,7 @@ GEM
24
24
  mocha (0.9.8)
25
25
  rake
26
26
  multi_json (1.0.3)
27
- rake (0.9.2)
27
+ rake (0.9.2.2)
28
28
  ruby-debug (0.10.4)
29
29
  columnize (>= 0.1)
30
30
  ruby-debug-base (~> 0.10.4.0)
@@ -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 => [:java_compile, :test]
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 => :java_compile
13
- task :install => :java_compile
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 "Build all adapters"
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 "Release all adapters"
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
@@ -40,7 +40,6 @@ module ::ArJdbc
40
40
  case field_type
41
41
  when /smallint/i then :boolean
42
42
  when /real/i then :float
43
- when /decimal/i then :decimal
44
43
  else
45
44
  super
46
45
  end
@@ -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
@@ -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'] == '2'}],
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'] == '-7'},
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}]
@@ -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::Column)}]
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 Column
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 /decimal/i then :decimal
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
- "1"
140
+ "1"
136
141
  end
137
142
 
138
143
  def quoted_false
139
- "0"
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::MysqlColumn.new(field["Field"], field["Default"], field["Type"], field["Null"] == "YES")
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
- row = res.detect {|row| row["Variable_name"] == var }
312
- row && row["Value"]
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::MysqlColumn
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
- execute sql.gsub('?') { quote(*binds.shift.reverse) }, name
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
- Integer(select_value("SELECT last_insert_rowid()"))
155
+ @connection.last_insert_row_id
156
156
  end
157
157
 
158
158
  def tables(name = nil) #:nodoc:
@@ -1,6 +1,6 @@
1
1
  module ArJdbc
2
2
  module Version
3
- VERSION = "1.2.0"
3
+ VERSION = "1.2.1"
4
4
  end
5
5
  end
6
6
  # Compatibility with older versions of ar-jdbc for other extensions out there
@@ -0,0 +1,11 @@
1
+ module Bundler
2
+ class GemHelper
3
+ def guard_already_tagged
4
+ # parent project performs the tag
5
+ end
6
+ def tag_version
7
+ Bundler.ui.confirm "Parent project tagged #{version_tag}"
8
+ yield if block_given?
9
+ end
10
+ end
11
+ end
@@ -1,25 +1,23 @@
1
- def java_classpath_arg # myriad of ways to discover JRuby classpath
2
- begin
3
- cpath = Java::java.lang.System.getProperty('java.class.path').split(File::PATH_SEPARATOR)
4
- cpath += Java::java.lang.System.getProperty('sun.boot.class.path').split(File::PATH_SEPARATOR)
5
- jruby_cpath = cpath.compact.join(File::PATH_SEPARATOR)
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
- jar_name = File.join(*%w(lib arjdbc jdbc adapter_java.jar))
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
- desc "Compile the native Java code."
18
- task :java_compile do
19
- debug = ENV['DEBUG'] ? '-g' : ''
20
- pkg_classes = File.join(*%w(pkg classes))
21
- mkdir_p pkg_classes
22
- sh "javac -target 1.5 -source 1.5 #{debug} -d pkg/classes #{java_classpath_arg} #{FileList['src/java/**/*.java'].join(' ')}"
23
- sh "jar cf #{jar_name} -C #{pkg_classes} ."
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