activerecord-jdbc-adapter 0.9.5-java → 0.9.6-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.
@@ -1,3 +1,17 @@
1
+ == 0.9.6
2
+
3
+ - The Oracle release!
4
+ - Oracle should be working much better with this release. Also updated
5
+ to work with Rails 3.
6
+ - Get all unit tests running cleanly on Oracle, fixing previous
7
+ datetime/timezone issues.
8
+ - ACTIVERECORD_JDBC-83: Add :sequence_start_value option to
9
+ create_table, following oracle_enhanced adapter
10
+ - ACTIVERECORD_JDBC-33: Don't double-quote table names in oracle
11
+ - ACTIVERECORD_JDBC-17: Fix Oracle primary keys so that /^NUMBER$/ => :integer
12
+ - Fix remaining blockers ACTIVERECORD_JDBC-82, JRUBY-3675,
13
+ ACTIVERECORD_JDBC-22, ACTIVERECORD_JDBC-27, JRUBY-4759
14
+
1
15
  == 0.9.5
2
16
 
3
17
  - The MSSQL release, courtesy of Mike Williams and Lonely
@@ -56,21 +56,36 @@ module JdbcSpec
56
56
  jdbc_connection(config)
57
57
  end
58
58
  end
59
+
60
+ module QuotedPrimaryKeyExtension
61
+ def self.extended(base)
62
+ # Rails 3 method Rails 2 method
63
+ meth = [:arel_attributes_values, :attributes_with_quotes].detect do |m|
64
+ base.private_instance_methods.include?(m.to_s)
65
+ end
66
+ pk_hash_key = "self.class.primary_key"
67
+ pk_hash_value = '"?"'
68
+ if meth == :arel_attributes_values
69
+ pk_hash_key = "self.class.arel_table[#{pk_hash_key}]"
70
+ pk_hash_value = "Arel::SqlLiteral.new(#{pk_hash_value})"
71
+ end
72
+ if meth
73
+ base.module_eval %{
74
+ alias :#{meth}_pre_pk :#{meth}
75
+ def #{meth}(include_primary_key = true, *args) #:nodoc:
76
+ aq = #{meth}_pre_pk(include_primary_key, *args)
77
+ aq[#{pk_hash_key}] = #{pk_hash_value} if include_primary_key && aq[#{pk_hash_key}].nil?
78
+ aq
79
+ end
80
+ }
81
+ end
82
+ end
83
+ end
59
84
  end
60
85
 
61
86
  module ActiveRecord
62
87
  class Base
63
88
  extend JdbcSpec::ActiveRecordExtensions
64
- if respond_to?(:attributes_with_quotes)
65
- alias :attributes_with_quotes_pre_oracle :attributes_with_quotes
66
- def attributes_with_quotes(include_primary_key = true, *args) #:nodoc:
67
- aq = attributes_with_quotes_pre_oracle(include_primary_key, *args)
68
- if connection.class == ConnectionAdapters::JdbcAdapter && (connection.is_a?(JdbcSpec::Oracle) || connection.is_a?(JdbcSpec::Mimer))
69
- aq[self.class.primary_key] = "?" if include_primary_key && aq[self.class.primary_key].nil?
70
- end
71
- aq
72
- end
73
- end
74
89
  end
75
90
 
76
91
  module ConnectionAdapters
@@ -1,5 +1,9 @@
1
1
  module JdbcSpec
2
2
  module Mimer
3
+ def self.extended(mod)
4
+ ActiveRecord::Base.extend JdbcSpec::QuotedPrimaryKeyExtension
5
+ end
6
+
3
7
  def self.adapter_matcher(name, *)
4
8
  name =~ /mimer/i ? self : false
5
9
  end
@@ -26,8 +26,10 @@ module ::JdbcSpec
26
26
  ActiveRecord::Base.after_save :after_save_with_oracle_lob
27
27
  @lob_callback_added = true
28
28
  end
29
+ ActiveRecord::Base.extend JdbcSpec::QuotedPrimaryKeyExtension
29
30
  mod.class.class_eval do
30
- alias_chained_method :insert, :query_dirty, :jdbc_oracle_insert
31
+ alias_chained_method :insert, :query_dirty, :insert
32
+ alias_chained_method :columns, :query_cache, :columns
31
33
  end
32
34
  end
33
35
 
@@ -40,6 +42,13 @@ module ::JdbcSpec
40
42
  end
41
43
 
42
44
  module Column
45
+ def primary=(val)
46
+ super
47
+ if val && @sql_type =~ /^NUMBER$/i
48
+ @type = :integer
49
+ end
50
+ end
51
+
43
52
  def type_cast(value)
44
53
  return nil if value.nil?
45
54
  case type
@@ -63,8 +72,8 @@ module ::JdbcSpec
63
72
  end
64
73
 
65
74
  def self.guess_date_or_time(value)
66
- (value.hour == 0 && value.min == 0 && value.sec == 0) ?
67
- new_date(value.year, value.month, value.day) : value
75
+ (value && value.hour == 0 && value.min == 0 && value.sec == 0) ?
76
+ Date.new(value.year, value.month, value.day) : value
68
77
  end
69
78
 
70
79
  private
@@ -74,7 +83,7 @@ module ::JdbcSpec
74
83
  when /char/i then :string
75
84
  when /float|double/i then :float
76
85
  when /int/i then :integer
77
- when /num|dec|real/i then @scale == 0 ? :integer : :decimal
86
+ when /num|dec|real/i then extract_scale(field_type) == 0 ? :integer : :decimal
78
87
  when /date|time/i then :datetime
79
88
  when /clob/i then :text
80
89
  when /blob/i then :binary
@@ -115,8 +124,9 @@ module ::JdbcSpec
115
124
  def create_table(name, options = {}) #:nodoc:
116
125
  super(name, options)
117
126
  seq_name = options[:sequence_name] || "#{name}_seq"
127
+ start_value = options[:sequence_start_value] || 10000
118
128
  raise ActiveRecord::StatementInvalid.new("name #{seq_name} too long") if seq_name.length > table_alias_length
119
- execute "CREATE SEQUENCE #{seq_name} START WITH 10000" unless options[:id] == false
129
+ execute "CREATE SEQUENCE #{seq_name} START WITH #{start_value}" unless options[:id] == false
120
130
  end
121
131
 
122
132
  def rename_table(name, new_name) #:nodoc:
@@ -138,10 +148,14 @@ module ::JdbcSpec
138
148
  recreate_database(name)
139
149
  end
140
150
 
141
- def jdbc_oracle_insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
142
- if id_value || pk.nil? # Pre-assigned id or table without a primary key
151
+ def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
152
+ if (id_value && !id_value.respond_to?(:to_sql)) || pk.nil?
153
+ # Pre-assigned id or table without a primary key
154
+ # Presence of #to_sql means an Arel literal bind variable
155
+ # that should use #execute_id_insert below
143
156
  execute sql, name
144
- else # Assume the sql contains a bind-variable for the id
157
+ else
158
+ # Assume the sql contains a bind-variable for the id
145
159
  # Extract the table from the insert sql. Yuck.
146
160
  table = sql.split(" ", 4)[2].gsub('"', '')
147
161
  sequence_name ||= default_sequence_name(table)
@@ -313,6 +327,12 @@ module ::JdbcSpec
313
327
  #
314
328
  # see: abstract/quoting.rb
315
329
 
330
+ # See ACTIVERECORD_JDBC-33 for details -- better to not quote
331
+ # table names, esp. if they have schemas.
332
+ def quote_table_name(name) #:nodoc:
333
+ name.to_s
334
+ end
335
+
316
336
  # Camelcase column names need to be quoted.
317
337
  # Nonquoted identifiers can contain only alphanumeric characters from your
318
338
  # database character set and the underscore (_), dollar sign ($), and pound sign (#).
@@ -335,7 +355,7 @@ module ::JdbcSpec
335
355
  %Q{empty_#{ column.sql_type.downcase rescue 'blob' }()}
336
356
  end
337
357
  else
338
- if column.respond_to?(:primary) && column.primary
358
+ if column.respond_to?(:primary) && column.primary && column.klass != String
339
359
  return value.to_i.to_s
340
360
  end
341
361
  quoted = super
@@ -347,7 +367,7 @@ module ::JdbcSpec
347
367
  end
348
368
 
349
369
  def quoted_date(value)
350
- %Q{TIMESTAMP'#{value.strftime("%Y-%m-%d %H:%M:%S")}'}
370
+ %Q{TIMESTAMP'#{super}'}
351
371
  end
352
372
 
353
373
  def quoted_true #:nodoc:
@@ -1,5 +1,5 @@
1
1
  module JdbcAdapter
2
2
  module Version
3
- VERSION = "0.9.5"
3
+ VERSION = "0.9.6"
4
4
  end
5
5
  end
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  **** BEGIN LICENSE BLOCK *****
3
- * Copyright (c) 2006-2009 Nick Sieger <nick@nicksieger.com>
3
+ * Copyright (c) 2006-2010 Nick Sieger <nick@nicksieger.com>
4
4
  * Copyright (c) 2006-2007 Ola Bini <ola.bini@gmail.com>
5
5
  * Copyright (c) 2008-2009 Thomas E Enebo <enebo@acm.org>
6
6
  *
@@ -117,7 +117,7 @@ public class RubyJdbcConnection extends RubyObject {
117
117
  throws SQLException, IOException {
118
118
  return (IRubyObject) withConnectionAndRetry(context, new SQLBlock() {
119
119
  public Object call(Connection c) throws SQLException {
120
- ResultSet results = null;
120
+ ResultSet results = null, pkeys = null;
121
121
  try {
122
122
  String table_name = rubyApi.convertToRubyString(args[0]).getUnicodeValue();
123
123
  String schemaName = null;
@@ -143,9 +143,11 @@ public class RubyJdbcConnection extends RubyObject {
143
143
  }
144
144
 
145
145
  results = metadata.getColumns(c.getCatalog(),schemaName,table_name,null);
146
- return unmarshal_columns(context, metadata, results);
146
+ pkeys = metadata.getPrimaryKeys(c.getCatalog(),schemaName,table_name);
147
+ return unmarshal_columns(context, metadata, results, pkeys);
147
148
  } finally {
148
149
  close(results);
150
+ close(pkeys);
149
151
  }
150
152
  }
151
153
  });
@@ -991,22 +993,28 @@ public class RubyJdbcConnection extends RubyObject {
991
993
  }
992
994
 
993
995
  private IRubyObject unmarshal_columns(ThreadContext context, DatabaseMetaData metadata,
994
- ResultSet rs) throws SQLException {
996
+ ResultSet rs, ResultSet pkeys) throws SQLException {
995
997
  try {
996
998
  Ruby runtime = context.getRuntime();
997
999
  List columns = new ArrayList();
1000
+ List pkeyNames = new ArrayList();
998
1001
  String clzName = metadata.getClass().getName().toLowerCase();
999
1002
  boolean isOracle = clzName.indexOf("oracle") != -1 || clzName.indexOf("oci") != -1;
1000
1003
 
1001
1004
  RubyHash types = (RubyHash) native_database_types();
1002
1005
  IRubyObject jdbcCol = getConnectionAdapters(runtime).getConstant("JdbcColumn");
1003
1006
 
1004
- while(rs.next()) {
1007
+ while (pkeys.next()) {
1008
+ pkeyNames.add(pkeys.getString(COLUMN_NAME));
1009
+ }
1010
+
1011
+ while (rs.next()) {
1012
+ String colName = rs.getString(COLUMN_NAME);
1005
1013
  IRubyObject column = jdbcCol.callMethod(context, "new",
1006
1014
  new IRubyObject[] {
1007
1015
  getInstanceVariable("@config"),
1008
1016
  RubyString.newUnicodeString(runtime,
1009
- caseConvertIdentifierForRails(metadata, rs.getString(COLUMN_NAME))),
1017
+ caseConvertIdentifierForRails(metadata, colName)),
1010
1018
  defaultValueFromResultSet(runtime, rs),
1011
1019
  RubyString.newUnicodeString(runtime, typeFromResultSet(rs, isOracle)),
1012
1020
  runtime.newBoolean(!rs.getString(IS_NULLABLE).trim().equals("NO"))
@@ -1014,12 +1022,15 @@ public class RubyJdbcConnection extends RubyObject {
1014
1022
  columns.add(column);
1015
1023
 
1016
1024
  IRubyObject tp = (IRubyObject)types.fastARef(column.callMethod(context,"type"));
1017
- if(tp != null && !tp.isNil() && tp.callMethod(context, "[]", runtime.newSymbol("limit")).isNil()) {
1025
+ if (tp != null && !tp.isNil() && tp.callMethod(context, "[]", runtime.newSymbol("limit")).isNil()) {
1018
1026
  column.callMethod(context, "limit=", runtime.getNil());
1019
1027
  if(!column.callMethod(context, "type").equals(runtime.newSymbol("decimal"))) {
1020
1028
  column.callMethod(context, "precision=", runtime.getNil());
1021
1029
  }
1022
1030
  }
1031
+ if (pkeyNames.contains(colName)) {
1032
+ column.callMethod(context, "primary=", runtime.getTrue());
1033
+ }
1023
1034
  }
1024
1035
  return runtime.newArray(columns);
1025
1036
  } finally {
@@ -6,24 +6,49 @@ class OracleSimpleTest < Test::Unit::TestCase
6
6
  end
7
7
 
8
8
  class OracleSpecificTest < Test::Unit::TestCase
9
- include MultibyteTestMethods
9
+ include MultibyteTestMethods # so we can get @java_con
10
10
 
11
11
  def setup
12
12
  super
13
- @java_con.createStatement.execute "CREATE TABLE DEFAULT_NUMBER (VALUE NUMBER)"
14
- @java_con.createStatement.execute "INSERT INTO DEFAULT_NUMBER (VALUE) VALUES (0.076)"
13
+ @java_con.createStatement.execute "CREATE TABLE DEFAULT_NUMBER (VALUE NUMBER, DATUM DATE)"
14
+ @java_con.createStatement.execute "INSERT INTO DEFAULT_NUMBER (VALUE, DATUM) VALUES (0.076, TIMESTAMP'2009-11-05 00:00:00')"
15
+ @java_con.createStatement.execute "CREATE SYNONYM POSTS FOR ENTRIES"
16
+ @klass = Class.new(ActiveRecord::Base)
17
+ @klass.set_table_name "DEFAULT_NUMBER"
15
18
  end
16
19
 
17
20
  def teardown
18
21
  @java_con.createStatement.execute "DROP TABLE DEFAULT_NUMBER"
22
+ @java_con.createStatement.execute "DROP SYNONYM POSTS"
19
23
  super
20
24
  end
21
25
 
22
-
23
26
  def test_default_number_precision
24
- klass = Class.new(ActiveRecord::Base)
25
- klass.set_table_name "DEFAULT_NUMBER"
26
- obj = klass.find(:first)
27
+ obj = @klass.find(:first)
27
28
  assert_equal 0.076, obj.value
28
29
  end
30
+
31
+ # JRUBY-3675, ACTIVERECORD_JDBC-22
32
+ def test_load_date
33
+ obj = @klass.find(:first)
34
+ assert_not_nil obj.datum, "no date"
35
+ end
36
+
37
+ def test_load_null_date
38
+ @java_con.createStatement.execute "UPDATE DEFAULT_NUMBER SET DATUM = NULL"
39
+ obj = @klass.find(:first)
40
+ assert obj.datum.nil?
41
+ end
42
+
43
+ def test_model_access_by_synonym
44
+ @klass.set_table_name "POSTS"
45
+ entry_columns = Entry.columns_hash
46
+ @klass.columns.each do |c|
47
+ ec = entry_columns[c.name]
48
+ assert ec
49
+ assert_equal ec.sql_type, c.sql_type
50
+ assert_equal ec.type, c.type
51
+ end
52
+ end
53
+
29
54
  end if defined?(JRUBY_VERSION)
@@ -105,6 +105,20 @@ module SimpleTestMethods
105
105
  end
106
106
 
107
107
  if Time.respond_to?(:zone)
108
+ def test_save_time_with_utc
109
+ current_zone = Time.zone
110
+ default_zone = ActiveRecord::Base.default_timezone
111
+ ActiveRecord::Base.default_timezone = Time.zone = :utc
112
+ now = Time.now
113
+ my_time = Time.local now.year, now.month, now.day, now.hour, now.min, now.sec
114
+ m = DbType.create! :sample_datetime => my_time
115
+ m.reload
116
+ assert_equal my_time, m.sample_datetime
117
+ rescue
118
+ Time.zone = current_zone
119
+ ActiveRecord::Base.default_timezone = default_zone
120
+ end
121
+
108
122
  def test_save_time
109
123
  t = Time.now
110
124
  #precision will only be expected to the second.
@@ -156,7 +170,12 @@ module SimpleTestMethods
156
170
  e.sample_date = date
157
171
  e.save!
158
172
  e = DbType.find(:first)
159
- assert_equal date, e.sample_date
173
+ if DbType.columns_hash["sample_date"].type == :datetime
174
+ # Oracle doesn't distinguish btw date/datetime
175
+ assert_equal date, e.sample_date.to_date
176
+ else
177
+ assert_equal date, e.sample_date
178
+ end
160
179
  end
161
180
 
162
181
  def test_boolean
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 9
8
- - 5
9
- version: 0.9.5
8
+ - 6
9
+ version: 0.9.6
10
10
  platform: java
11
11
  authors:
12
12
  - Nick Sieger, Ola Bini and JRuby contributors
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-22 00:00:00 -05:00
17
+ date: 2010-05-05 00:00:00 -05:00
18
18
  default_executable:
19
19
  dependencies: []
20
20