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.
- data/History.txt +14 -0
- data/lib/active_record/connection_adapters/jdbc_adapter.rb +25 -10
- data/lib/jdbc_adapter/jdbc_adapter_internal.jar +0 -0
- data/lib/jdbc_adapter/jdbc_mimer.rb +4 -0
- data/lib/jdbc_adapter/jdbc_oracle.rb +30 -10
- data/lib/jdbc_adapter/version.rb +1 -1
- data/src/java/jdbc_adapter/RubyJdbcConnection.java +18 -7
- data/test/oracle_simple_test.rb +32 -7
- data/test/simple.rb +20 -1
- metadata +3 -3
data/History.txt
CHANGED
@@ -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
|
Binary file
|
@@ -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, :
|
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
|
-
|
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
|
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
|
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
|
142
|
-
if id_value || pk.nil?
|
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
|
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'#{
|
370
|
+
%Q{TIMESTAMP'#{super}'}
|
351
371
|
end
|
352
372
|
|
353
373
|
def quoted_true #:nodoc:
|
data/lib/jdbc_adapter/version.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
**** BEGIN LICENSE BLOCK *****
|
3
|
-
* Copyright (c) 2006-
|
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
|
-
|
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
|
-
|
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(
|
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,
|
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 {
|
data/test/oracle_simple_test.rb
CHANGED
@@ -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
|
-
|
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)
|
data/test/simple.rb
CHANGED
@@ -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
|
-
|
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
|
-
-
|
9
|
-
version: 0.9.
|
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-
|
17
|
+
date: 2010-05-05 00:00:00 -05:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|