ActiveRecord-JDBC 0.4 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. data/History.txt +12 -0
  2. data/Manifest.txt +13 -0
  3. data/Rakefile +18 -10
  4. data/lib/active_record/connection_adapters/derby_adapter.rb +1 -0
  5. data/lib/active_record/connection_adapters/h2_adapter.rb +1 -0
  6. data/lib/active_record/connection_adapters/hsqldb_adapter.rb +1 -0
  7. data/lib/active_record/connection_adapters/jdbc_adapter.rb +124 -56
  8. data/lib/active_record/connection_adapters/jndi_adapter.rb +1 -0
  9. data/lib/active_record/connection_adapters/mysql_adapter.rb +1 -0
  10. data/lib/active_record/connection_adapters/oracle_adapter.rb +1 -0
  11. data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -0
  12. data/lib/jdbc_adapter/jdbc_db2.rb +21 -0
  13. data/lib/jdbc_adapter/jdbc_derby.rb +22 -101
  14. data/lib/jdbc_adapter/jdbc_firebird.rb +5 -1
  15. data/lib/jdbc_adapter/jdbc_hsqldb.rb +23 -1
  16. data/lib/jdbc_adapter/jdbc_mimer.rb +4 -2
  17. data/lib/jdbc_adapter/jdbc_mssql.rb +149 -67
  18. data/lib/jdbc_adapter/jdbc_mysql.rb +22 -2
  19. data/lib/jdbc_adapter/jdbc_oracle.rb +80 -15
  20. data/lib/jdbc_adapter/jdbc_postgre.rb +132 -4
  21. data/lib/jdbc_adapter_internal.jar +0 -0
  22. data/src/java/JDBCDerbySpec.java +323 -0
  23. data/src/java/JDBCMySQLSpec.java +83 -0
  24. data/src/java/JdbcAdapterInternalService.java +802 -0
  25. data/test/activerecord/connection_adapters/type_conversion_test.rb +1 -0
  26. data/test/db/derby.rb +2 -5
  27. data/test/db/h2.rb +2 -5
  28. data/test/db/hsqldb.rb +2 -6
  29. data/test/db/jdbc.rb +9 -0
  30. data/test/db/mysql.rb +4 -15
  31. data/test/db/postgres.rb +2 -3
  32. data/test/generic_jdbc_connection_test.rb +9 -0
  33. data/test/jdbc_adapter/jdbc_db2_test.rb +21 -0
  34. data/test/simple.rb +6 -8
  35. 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 : :float
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 =~ /^\s*null\s*$/i
30
+ return nil if value.nil? || value == "(NULL)"
21
31
  case type
22
- when :string then value
23
- when :integer then value == true || value == false ? value == true ? 1 : 0 : value.to_i
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 :float then value.to_f
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.to_s == '1'
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
- if column && column.type == :primary_key
91
- return value.to_s
92
- end
93
- case value
94
- when String
95
- if column && column.type == :binary && column.class.respond_to?(:string_to_binary)
96
- val = quote_string(column.class.string_to_binary(value))
97
- "'#{val}'"
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
- def add_limit_offset!(sql, options)
128
- if options[:limit] and options[:offset]
129
- total_rows = @connection.select_all("SELECT count(*) as TotalRows from (#{sql.gsub(/\bSELECT\b/i, "SELECT TOP 1000000000")}) tally")[0][:TotalRows].to_i
130
- if (options[:limit] + options[:offset]) >= total_rows
131
- options[:limit] = (total_rows - options[:offset] >= 0) ? (total_rows - options[:offset]) : 0
132
- end
133
- sql.sub!(/^\s*SELECT/i, "SELECT * FROM (SELECT TOP #{options[:limit]} * FROM (SELECT TOP #{options[:limit] + options[:offset]} ")
134
- sql << ") AS tmp1"
135
- if options[:order]
136
- options[:order] = options[:order].split(',').map do |field|
137
- parts = field.split(" ")
138
- tc = parts[0]
139
- if sql =~ /\.\[/ and tc =~ /\./ # if column quoting used in query
140
- tc.gsub!(/\./, '\\.\\[')
141
- tc << '\\]'
142
- end
143
- if sql =~ /#{tc} AS (t\d_r\d\d?)/
144
- parts[0] = $1
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
- parts.join(' ')
147
- end.join(', ')
148
- sql << " ORDER BY #{change_order_direction(options[:order])}) AS tmp2 ORDER BY #{options[:order]}"
149
- else
150
- sql << " ) AS tmp2"
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[:default]
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\(1\)/i
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 JdbcSpec
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 : :string
23
- when /num|float|double|dec|real|int/i : @scale == 0 ? :integer : :float
24
- when /date|time/i : @name =~ /_at$/ ? :time : :datetime
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 (value.is_a? Time) ? value : cast_to_time(value)
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