ActiveRecord-JDBC 0.4 → 0.5
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 +12 -0
- data/Manifest.txt +13 -0
- data/Rakefile +18 -10
- data/lib/active_record/connection_adapters/derby_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/h2_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/hsqldb_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/jdbc_adapter.rb +124 -56
- data/lib/active_record/connection_adapters/jndi_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/oracle_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -0
- data/lib/jdbc_adapter/jdbc_db2.rb +21 -0
- data/lib/jdbc_adapter/jdbc_derby.rb +22 -101
- data/lib/jdbc_adapter/jdbc_firebird.rb +5 -1
- data/lib/jdbc_adapter/jdbc_hsqldb.rb +23 -1
- data/lib/jdbc_adapter/jdbc_mimer.rb +4 -2
- data/lib/jdbc_adapter/jdbc_mssql.rb +149 -67
- data/lib/jdbc_adapter/jdbc_mysql.rb +22 -2
- data/lib/jdbc_adapter/jdbc_oracle.rb +80 -15
- data/lib/jdbc_adapter/jdbc_postgre.rb +132 -4
- data/lib/jdbc_adapter_internal.jar +0 -0
- data/src/java/JDBCDerbySpec.java +323 -0
- data/src/java/JDBCMySQLSpec.java +83 -0
- data/src/java/JdbcAdapterInternalService.java +802 -0
- data/test/activerecord/connection_adapters/type_conversion_test.rb +1 -0
- data/test/db/derby.rb +2 -5
- data/test/db/h2.rb +2 -5
- data/test/db/hsqldb.rb +2 -6
- data/test/db/jdbc.rb +9 -0
- data/test/db/mysql.rb +4 -15
- data/test/db/postgres.rb +2 -3
- data/test/generic_jdbc_connection_test.rb +9 -0
- data/test/jdbc_adapter/jdbc_db2_test.rb +21 -0
- data/test/simple.rb +6 -8
- metadata +15 -2
@@ -1,5 +1,9 @@
|
|
1
|
-
module JdbcSpec
|
1
|
+
module ::JdbcSpec
|
2
2
|
module FireBird
|
3
|
+
def self.adapter_selector
|
4
|
+
[/firebird/i, lambda{|cfg,adapt| adapt.extend(::JdbcSpec::FireBird)}]
|
5
|
+
end
|
6
|
+
|
3
7
|
def modify_types(tp)
|
4
8
|
tp[:primary_key] = 'INTEGER NOT NULL PRIMARY KEY'
|
5
9
|
tp[:string][:limit] = 252
|
@@ -1,5 +1,27 @@
|
|
1
|
-
module JdbcSpec
|
1
|
+
module ::JdbcSpec
|
2
|
+
module ActiveRecordExtensions
|
3
|
+
def hsqldb_connection(config)
|
4
|
+
config[:url] ||= "jdbc:hsqldb:#{config[:database]}"
|
5
|
+
config[:driver] ||= "org.hsqldb.jdbcDriver"
|
6
|
+
embedded_driver(config)
|
7
|
+
end
|
8
|
+
|
9
|
+
def h2_connection(config)
|
10
|
+
config[:url] ||= "jdbc:h2:#{config[:database]}"
|
11
|
+
config[:driver] ||= "org.h2.Driver"
|
12
|
+
embedded_driver(config)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
2
16
|
module HSQLDB
|
17
|
+
def self.column_selector
|
18
|
+
[/hsqldb|\.h2\./i, lambda {|cfg,col| col.extend(::JdbcSpec::HSQLDB::Column)}]
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.adapter_selector
|
22
|
+
[/hsqldb|\.h2\./i, lambda {|cfg,adapt| adapt.extend(::JdbcSpec::HSQLDB)}]
|
23
|
+
end
|
24
|
+
|
3
25
|
module Column
|
4
26
|
def type_cast(value)
|
5
27
|
return nil if value.nil? || value =~ /^\s*null\s*$/i
|
@@ -1,5 +1,9 @@
|
|
1
1
|
module JdbcSpec
|
2
2
|
module Mimer
|
3
|
+
def self.adapter_selector
|
4
|
+
[/mimer/i, lambda {|cfg,adapt| adapt.extend(::JdbcSpec::Mimer)}]
|
5
|
+
end
|
6
|
+
|
3
7
|
def modify_types(tp)
|
4
8
|
tp[:primary_key] = "INTEGER NOT NULL PRIMARY KEY"
|
5
9
|
tp[:boolean][:limit] = nil
|
@@ -110,7 +114,6 @@ module JdbcSpec
|
|
110
114
|
end
|
111
115
|
|
112
116
|
def _execute(sql, name = nil)
|
113
|
-
log_no_bench(sql, name) do
|
114
117
|
if sql =~ /^select/i
|
115
118
|
@offset ||= 0
|
116
119
|
if !@limit || @limit == -1
|
@@ -122,7 +125,6 @@ module JdbcSpec
|
|
122
125
|
else
|
123
126
|
@connection.execute_update(sql)
|
124
127
|
end
|
125
|
-
end
|
126
128
|
ensure
|
127
129
|
@limit = @offset = nil
|
128
130
|
end
|
@@ -1,10 +1,20 @@
|
|
1
1
|
module JdbcSpec
|
2
2
|
module MsSQL
|
3
|
+
def self.column_selector
|
4
|
+
[/sqlserver|tds/i, lambda {|cfg,col| col.extend(::JdbcSpec::MsSQL::Column)}]
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.adapter_selector
|
8
|
+
[/sqlserver|tds/i, lambda {|cfg,adapt| adapt.extend(::JdbcSpec::MsSQL)}]
|
9
|
+
end
|
10
|
+
|
3
11
|
module Column
|
12
|
+
attr_accessor :identity, :is_special
|
13
|
+
|
4
14
|
def simplified_type(field_type)
|
5
15
|
case field_type
|
6
16
|
when /int|bigint|smallint|tinyint/i then :integer
|
7
|
-
when /float|double|decimal|money|numeric|real|smallmoney/i then @scale == 0 ? :integer : :
|
17
|
+
when /float|double|decimal|money|numeric|real|smallmoney/i then @scale == 0 ? :integer : :decimal
|
8
18
|
when /datetime|smalldatetime/i then :datetime
|
9
19
|
when /timestamp/i then :timestamp
|
10
20
|
when /time/i then :time
|
@@ -17,21 +27,26 @@ module JdbcSpec
|
|
17
27
|
end
|
18
28
|
|
19
29
|
def type_cast(value)
|
20
|
-
return nil if value.nil? || value
|
30
|
+
return nil if value.nil? || value == "(NULL)"
|
21
31
|
case type
|
22
|
-
when :string
|
23
|
-
when :integer
|
32
|
+
when :string then unquote value
|
33
|
+
when :integer then unquote(value).to_i rescue value ? 1 : 0
|
24
34
|
when :primary_key then value == true || value == false ? value == true ? 1 : 0 : value.to_i
|
25
|
-
when :
|
35
|
+
when :decimal then self.class.value_to_decimal(value)
|
26
36
|
when :datetime then cast_to_datetime(value)
|
27
37
|
when :timestamp then cast_to_time(value)
|
28
38
|
when :time then cast_to_time(value)
|
29
39
|
when :date then cast_to_datetime(value)
|
30
|
-
when :boolean then value == true or (value =~ /^t(rue)?$/i) == 0 or value
|
40
|
+
when :boolean then value == true or (value =~ /^t(rue)?$/i) == 0 or unquote(value)=="1"
|
41
|
+
when :binary then unquote value
|
31
42
|
else value
|
32
43
|
end
|
33
44
|
end
|
34
|
-
|
45
|
+
|
46
|
+
def unquote(value)
|
47
|
+
value.to_s.sub(/^\([\(\']?/, "").sub(/[\'\)]?\)$/, "")
|
48
|
+
end
|
49
|
+
|
35
50
|
def cast_to_time(value)
|
36
51
|
return value if value.is_a?(Time)
|
37
52
|
time_array = ParseDate.parsedate(value)
|
@@ -85,77 +100,70 @@ module JdbcSpec
|
|
85
100
|
tp[:binary] = { :name => "image"}
|
86
101
|
tp
|
87
102
|
end
|
88
|
-
|
103
|
+
|
89
104
|
def quote(value, column = nil)
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
else
|
99
|
-
"'#{quote_string(value)}'"
|
100
|
-
end
|
101
|
-
when NilClass then "NULL"
|
102
|
-
when TrueClass then '1'
|
103
|
-
when FalseClass then '0'
|
104
|
-
when Float, Fixnum, Bignum then value.to_s
|
105
|
-
when Date then "'#{value.to_s}'"
|
106
|
-
when Time, DateTime then "'#{value.strftime("%Y-%m-%d %H:%M:%S")}'"
|
107
|
-
else "'#{quote_string(value.to_yaml)}'"
|
108
|
-
end
|
105
|
+
return value.quoted_id if value.respond_to?(:quoted_id)
|
106
|
+
|
107
|
+
case value
|
108
|
+
when TrueClass then '1'
|
109
|
+
when FalseClass then '0'
|
110
|
+
when Time, DateTime then "'#{value.strftime("%Y%m%d %H:%M:%S")}'"
|
111
|
+
when Date then "'#{value.strftime("%Y%m%d")}'"
|
112
|
+
else super
|
109
113
|
end
|
114
|
+
end
|
110
115
|
|
111
116
|
def quote_string(string)
|
112
117
|
string.gsub(/\'/, "''")
|
113
118
|
end
|
114
119
|
|
115
|
-
def quoted_true
|
116
|
-
"1"
|
117
|
-
end
|
118
|
-
|
119
|
-
def quoted_false
|
120
|
-
"0"
|
121
|
-
end
|
122
|
-
|
123
120
|
def quote_column_name(name)
|
124
121
|
"[#{name}]"
|
125
122
|
end
|
123
|
+
|
124
|
+
def add_limit_offset!(sql, options)
|
125
|
+
if options[:limit] and options[:offset]
|
126
|
+
total_rows = select_all("SELECT count(*) as TotalRows from (#{sql.gsub(/\bSELECT(\s+DISTINCT)?\b/i, "SELECT#{$1} TOP 1000000000")}) tally")[0][:TotalRows].to_i
|
126
127
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
128
|
+
sql.sub!(/^\s*SELECT(\s+DISTINCT)?/i, "SELECT * FROM (SELECT TOP #{options[:limit]} * FROM (SELECT#{$1} TOP #{options[:limit] + options[:offset]} ")
|
129
|
+
sql << ") AS tmp1"
|
130
|
+
if options[:order]
|
131
|
+
options[:order] = options[:order].split(',').map do |field|
|
132
|
+
parts = field.split(" ")
|
133
|
+
tc = parts[0]
|
134
|
+
if sql =~ /\.\[/ and tc =~ /\./ # if column quoting used in query
|
135
|
+
tc.gsub!(/\./, '\\.\\[')
|
136
|
+
tc << '\\]'
|
137
|
+
end
|
138
|
+
if sql =~ /#{tc} AS (t\d_r\d\d?)/
|
139
|
+
parts[0] = $1
|
140
|
+
elsif parts[0] =~ /\w+\.(\w+)/
|
141
|
+
parts[0] = $1
|
142
|
+
end
|
143
|
+
parts.join(' ')
|
144
|
+
end.join(', ')
|
145
|
+
sql << " ORDER BY #{change_order_direction(options[:order])}) AS tmp2 ORDER BY #{options[:order]}"
|
146
|
+
else
|
147
|
+
sql << " ) AS tmp2"
|
145
148
|
end
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
149
|
+
elsif sql !~ /^\s*SELECT (@@|COUNT\()/i
|
150
|
+
sql.sub!(/^\s*SELECT(\s+DISTINCT)?/i) do
|
151
|
+
"SELECT#{$1} TOP #{options[:limit]}"
|
152
|
+
end unless options[:limit].nil?
|
153
|
+
end
|
151
154
|
end
|
152
|
-
elsif sql !~ /^\s*SELECT (@@|COUNT\()/i
|
153
|
-
sql.sub!(/^\s*SELECT([\s]*distinct)?/i) do
|
154
|
-
"SELECT#{$1} TOP #{options[:limit]}"
|
155
|
-
end unless options[:limit].nil?
|
156
|
-
end
|
157
|
-
end
|
158
155
|
|
156
|
+
|
157
|
+
def change_order_direction(order)
|
158
|
+
order.split(",").collect {|fragment|
|
159
|
+
case fragment
|
160
|
+
when /\bDESC\b/i then fragment.gsub(/\bDESC\b/i, "ASC")
|
161
|
+
when /\bASC\b/i then fragment.gsub(/\bASC\b/i, "DESC")
|
162
|
+
else String.new(fragment).split(',').join(' DESC,') + ' DESC'
|
163
|
+
end
|
164
|
+
}.join(",")
|
165
|
+
end
|
166
|
+
|
159
167
|
def recreate_database(name)
|
160
168
|
drop_database(name)
|
161
169
|
create_database(name)
|
@@ -179,15 +187,17 @@ module JdbcSpec
|
|
179
187
|
|
180
188
|
def change_column(table_name, column_name, type, options = {}) #:nodoc:
|
181
189
|
sql_commands = ["ALTER TABLE #{table_name} ALTER COLUMN #{column_name} #{type_to_sql(type, options[:limit])}"]
|
182
|
-
if options
|
190
|
+
if options_include_default?(options)
|
183
191
|
remove_default_constraint(table_name, column_name)
|
184
|
-
sql_commands << "ALTER TABLE #{table_name} ADD CONSTRAINT DF_#{table_name}_#{column_name} DEFAULT #{options[:default]} FOR #{column_name}"
|
192
|
+
sql_commands << "ALTER TABLE #{table_name} ADD CONSTRAINT DF_#{table_name}_#{column_name} DEFAULT #{quote(options[:default], options[:column])} FOR #{column_name}"
|
185
193
|
end
|
186
194
|
sql_commands.each {|c|
|
187
195
|
execute(c)
|
188
196
|
}
|
189
197
|
end
|
190
|
-
|
198
|
+
def change_column_default(table_name, column_name, default) #:nodoc:
|
199
|
+
execute "ALTER TABLE #{table_name} ADD CONSTRAINT DF_#{table_name}_#{column_name} DEFAULT #{quote(default, column_name)} FOR #{column_name}"
|
200
|
+
end
|
191
201
|
def remove_column(table_name, column_name)
|
192
202
|
remove_default_constraint(table_name, column_name)
|
193
203
|
execute "ALTER TABLE #{table_name} DROP COLUMN #{column_name}"
|
@@ -203,6 +213,78 @@ module JdbcSpec
|
|
203
213
|
def remove_index(table_name, options = {})
|
204
214
|
execute "DROP INDEX #{table_name}.#{index_name(table_name, options)}"
|
205
215
|
end
|
216
|
+
|
217
|
+
|
218
|
+
def columns(table_name, name = nil)
|
219
|
+
cc = super
|
220
|
+
cc.each do |col|
|
221
|
+
col.identity = true if col.sql_type =~ /identity/i
|
222
|
+
col.is_special = true if col.sql_type =~ /text|ntext|image/i
|
223
|
+
end
|
224
|
+
cc
|
225
|
+
end
|
226
|
+
|
227
|
+
def _execute(sql, name = nil)
|
228
|
+
if sql.lstrip =~ /^insert/i
|
229
|
+
if query_requires_identity_insert?(sql)
|
230
|
+
table_name = get_table_name(sql)
|
231
|
+
with_identity_insert_enabled(table_name) do
|
232
|
+
id = @connection.execute_insert(sql)
|
233
|
+
end
|
234
|
+
else
|
235
|
+
@connection.execute_insert(sql)
|
236
|
+
end
|
237
|
+
elsif sql.lstrip =~ /^\(?\s*(select|show)/i
|
238
|
+
@connection.execute_query(sql)
|
239
|
+
else
|
240
|
+
@connection.execute_update(sql)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
|
245
|
+
private
|
246
|
+
# Turns IDENTITY_INSERT ON for table during execution of the block
|
247
|
+
# N.B. This sets the state of IDENTITY_INSERT to OFF after the
|
248
|
+
# block has been executed without regard to its previous state
|
249
|
+
|
250
|
+
def with_identity_insert_enabled(table_name, &block)
|
251
|
+
set_identity_insert(table_name, true)
|
252
|
+
yield
|
253
|
+
ensure
|
254
|
+
set_identity_insert(table_name, false)
|
255
|
+
end
|
256
|
+
|
257
|
+
def set_identity_insert(table_name, enable = true)
|
258
|
+
execute "SET IDENTITY_INSERT #{table_name} #{enable ? 'ON' : 'OFF'}"
|
259
|
+
rescue Exception => e
|
260
|
+
raise ActiveRecordError, "IDENTITY_INSERT could not be turned #{enable ? 'ON' : 'OFF'} for table #{table_name}"
|
261
|
+
end
|
262
|
+
|
263
|
+
def get_table_name(sql)
|
264
|
+
if sql =~ /^\s*insert\s+into\s+([^\(\s]+)\s*|^\s*update\s+([^\(\s]+)\s*/i
|
265
|
+
$1
|
266
|
+
elsif sql =~ /from\s+([^\(\s]+)\s*/i
|
267
|
+
$1
|
268
|
+
else
|
269
|
+
nil
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
def identity_column(table_name)
|
274
|
+
@table_columns = {} unless @table_columns
|
275
|
+
@table_columns[table_name] = columns(table_name) if @table_columns[table_name] == nil
|
276
|
+
@table_columns[table_name].each do |col|
|
277
|
+
return col.name if col.identity
|
278
|
+
end
|
279
|
+
|
280
|
+
return nil
|
281
|
+
end
|
282
|
+
|
283
|
+
def query_requires_identity_insert?(sql)
|
284
|
+
table_name = get_table_name(sql)
|
285
|
+
id_column = identity_column(table_name)
|
286
|
+
sql =~ /\[#{id_column}\]/ ? table_name : nil
|
287
|
+
end
|
206
288
|
end
|
207
289
|
end
|
208
290
|
|
@@ -1,7 +1,27 @@
|
|
1
1
|
require 'active_record/connection_adapters/abstract/schema_definitions'
|
2
2
|
|
3
|
-
module JdbcSpec
|
3
|
+
module ::JdbcSpec
|
4
|
+
module ActiveRecordExtensions
|
5
|
+
def mysql_connection(config)
|
6
|
+
if config[:socket]
|
7
|
+
warn "AR-JDBC MySQL on JRuby does not support sockets"
|
8
|
+
end
|
9
|
+
config[:port] ||= 3306
|
10
|
+
config[:url] ||= "jdbc:mysql://#{config[:host]}:#{config[:port]}/#{config[:database]}"
|
11
|
+
config[:driver] = "com.mysql.jdbc.Driver"
|
12
|
+
jdbc_connection(config)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
4
16
|
module MySQL
|
17
|
+
def self.column_selector
|
18
|
+
[/mysql/i, lambda {|cfg,col| col.extend(::JdbcSpec::MySQL::Column)}]
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.adapter_selector
|
22
|
+
[/mysql/i, lambda {|cfg,adapt| adapt.extend(::JdbcSpec::MySQL)}]
|
23
|
+
end
|
24
|
+
|
5
25
|
def self.extended(adapter)
|
6
26
|
adapter.execute("SET SQL_AUTO_IS_NULL=0")
|
7
27
|
end
|
@@ -10,7 +30,7 @@ module JdbcSpec
|
|
10
30
|
TYPES_ALLOWING_EMPTY_STRING_DEFAULT = Set.new([:binary, :string, :text])
|
11
31
|
|
12
32
|
def simplified_type(field_type)
|
13
|
-
return :boolean if field_type =~ /tinyint\(1\)|bit
|
33
|
+
return :boolean if field_type =~ /tinyint\(1\)|bit/i
|
14
34
|
return :string if field_type =~ /enum/i
|
15
35
|
super
|
16
36
|
end
|
@@ -1,5 +1,42 @@
|
|
1
|
-
module
|
1
|
+
module ::ActiveRecord
|
2
|
+
class Base
|
3
|
+
# After setting large objects to empty, write data back with a helper method
|
4
|
+
after_save :write_lobs
|
5
|
+
def write_lobs() #:nodoc:
|
6
|
+
if connection.is_a?(JdbcSpec::Oracle)
|
7
|
+
self.class.columns.select { |c| c.sql_type =~ /LOB\(|LOB$/i }.each { |c|
|
8
|
+
value = self[c.name]
|
9
|
+
value = value.to_yaml if unserializable_attribute?(c.name, c)
|
10
|
+
next if value.nil? || (value == '')
|
11
|
+
|
12
|
+
connection.write_large_object(c.type == :binary, c.name, self.class.table_name, self.class.primary_key, quote_value(id), value)
|
13
|
+
}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private :write_lobs
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module ::JdbcSpec
|
22
|
+
module ActiveRecordExtensions
|
23
|
+
def oracle_connection(config)
|
24
|
+
config[:port] ||= 1521
|
25
|
+
config[:url] ||= "jdbc:oracle:thin:@#{config[:host]}:#{config[:port]}:#{config[:database]}"
|
26
|
+
config[:driver] ||= "oracle.jdbc.driver.OracleDriver"
|
27
|
+
jdbc_connection(config)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
2
31
|
module Oracle
|
32
|
+
def self.column_selector
|
33
|
+
[/oracle/i, lambda {|cfg,col| col.extend(::JdbcSpec::Oracle::Column)}]
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.adapter_selector
|
37
|
+
[/oracle/i, lambda {|cfg,adapt| adapt.extend(::JdbcSpec::Oracle)}]
|
38
|
+
end
|
39
|
+
|
3
40
|
module Column
|
4
41
|
def type_cast(value)
|
5
42
|
return nil if value.nil? || value =~ /^\s*null\s*$/i
|
@@ -8,39 +45,46 @@ module JdbcSpec
|
|
8
45
|
when :integer then defined?(value.to_i) ? value.to_i : (value ? 1 : 0)
|
9
46
|
when :primary_key then defined?(value.to_i) ? value.to_i : (value ? 1 : 0)
|
10
47
|
when :float then value.to_f
|
11
|
-
when :datetime then cast_to_date_or_time(value)
|
12
|
-
when :time then cast_to_time(value)
|
48
|
+
when :datetime then JdbcSpec::Oracle::Column.cast_to_date_or_time(value)
|
49
|
+
when :time then JdbcSpec::Oracle::Column.cast_to_time(value)
|
13
50
|
when :decimal then self.class.value_to_decimal(value)
|
14
51
|
when :boolean then self.class.value_to_boolean(value)
|
15
52
|
else value
|
16
53
|
end
|
17
54
|
end
|
18
55
|
|
56
|
+
def type_cast_code(var_name)
|
57
|
+
return "JdbcSpec::Oracle::Column.cast_to_date_or_time(#{var_name})" if type == :datetime
|
58
|
+
super
|
59
|
+
end
|
60
|
+
|
19
61
|
private
|
20
|
-
def simplified_type(field_type)
|
62
|
+
def simplified_type(field_type)
|
21
63
|
case field_type
|
22
|
-
when /char/i
|
23
|
-
when /
|
24
|
-
when /
|
64
|
+
when /char/i : :string
|
65
|
+
when /float|double/i : :float
|
66
|
+
when /int/i : :integer
|
67
|
+
when /num|dec|real/i : @scale == 0 ? :integer : :decimal
|
68
|
+
when /date|time/i : :datetime
|
25
69
|
when /clob/i : :text
|
26
70
|
when /blob/i : :binary
|
27
71
|
end
|
28
72
|
end
|
29
73
|
|
30
|
-
def cast_to_date_or_time(value)
|
74
|
+
def self.cast_to_date_or_time(value)
|
31
75
|
return value if value.is_a? Date
|
32
76
|
return nil if value.blank?
|
33
|
-
guess_date_or_time
|
77
|
+
guess_date_or_time((value.is_a? Time) ? value : cast_to_time(value))
|
34
78
|
end
|
35
79
|
|
36
|
-
def cast_to_time(value)
|
80
|
+
def self.cast_to_time(value)
|
37
81
|
return value if value.is_a? Time
|
38
82
|
time_array = ParseDate.parsedate value
|
39
83
|
time_array[0] ||= 2000; time_array[1] ||= 1; time_array[2] ||= 1;
|
40
84
|
Time.send(ActiveRecord::Base.default_timezone, *time_array) rescue nil
|
41
85
|
end
|
42
86
|
|
43
|
-
def guess_date_or_time(value)
|
87
|
+
def self.guess_date_or_time(value)
|
44
88
|
(value.hour == 0 and value.min == 0 and value.sec == 0) ?
|
45
89
|
Date.new(value.year, value.month, value.day) : value
|
46
90
|
end
|
@@ -65,6 +109,10 @@ module JdbcSpec
|
|
65
109
|
execute "DROP SEQUENCE #{name}_seq" rescue nil
|
66
110
|
end
|
67
111
|
|
112
|
+
def recreate_database(name)
|
113
|
+
tables.each{ |table| drop_table(table) }
|
114
|
+
end
|
115
|
+
|
68
116
|
def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
|
69
117
|
if pk.nil? # Who called us? What does the sql look like? No idea!
|
70
118
|
execute sql, name
|
@@ -79,15 +127,17 @@ module JdbcSpec
|
|
79
127
|
id_value
|
80
128
|
end
|
81
129
|
|
130
|
+
def indexes(table, name = nil)
|
131
|
+
@connection.indexes(table, name, @connection.connection.meta_data.user_name)
|
132
|
+
end
|
133
|
+
|
82
134
|
def _execute(sql, name = nil)
|
83
|
-
log_no_bench(sql, name) do
|
84
135
|
case sql.strip
|
85
136
|
when /^(select|show)/i:
|
86
137
|
@connection.execute_query(sql)
|
87
138
|
else
|
88
139
|
@connection.execute_update(sql)
|
89
140
|
end
|
90
|
-
end
|
91
141
|
end
|
92
142
|
|
93
143
|
def modify_types(tp)
|
@@ -147,7 +197,11 @@ module JdbcSpec
|
|
147
197
|
from user_tab_columns
|
148
198
|
where table_name = '#{table.to_a.first.last}'
|
149
199
|
order by column_id
|
150
|
-
}).map do |row|
|
200
|
+
}).map do |row|
|
201
|
+
row = row.inject({}) do |h,args|
|
202
|
+
h[args[0].downcase] = args[1]
|
203
|
+
h
|
204
|
+
end
|
151
205
|
col = "#{row['column_name'].downcase} #{row['data_type'].downcase}"
|
152
206
|
if row['data_type'] =='NUMBER' and !row['data_precision'].nil?
|
153
207
|
col << "(#{row['data_precision'].to_i}"
|
@@ -202,7 +256,7 @@ module JdbcSpec
|
|
202
256
|
return value.to_s
|
203
257
|
end
|
204
258
|
case value
|
205
|
-
when String : %Q{'#{quote_string(value)}'}
|
259
|
+
when String, ActiveSupport::Multibyte::Chars : %Q{'#{quote_string(value)}'}
|
206
260
|
when NilClass : 'null'
|
207
261
|
when TrueClass : '1'
|
208
262
|
when FalseClass : '0'
|
@@ -212,5 +266,16 @@ module JdbcSpec
|
|
212
266
|
end
|
213
267
|
end
|
214
268
|
end
|
269
|
+
|
270
|
+
private
|
271
|
+
|
272
|
+
def select(sql, name = nil)
|
273
|
+
records = execute(sql, name)
|
274
|
+
records.map do |col|
|
275
|
+
col.delete('raw_rnum_')
|
276
|
+
col
|
277
|
+
end
|
278
|
+
records
|
279
|
+
end
|
215
280
|
end
|
216
281
|
end
|