activerecord-jdbc-adapter 0.6

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.
Files changed (65) hide show
  1. data/History.txt +61 -0
  2. data/LICENSE +21 -0
  3. data/Manifest.txt +64 -0
  4. data/README.txt +116 -0
  5. data/Rakefile +146 -0
  6. data/lib/active_record/connection_adapters/derby_adapter.rb +13 -0
  7. data/lib/active_record/connection_adapters/h2_adapter.rb +1 -0
  8. data/lib/active_record/connection_adapters/hsqldb_adapter.rb +13 -0
  9. data/lib/active_record/connection_adapters/jdbc_adapter.rb +575 -0
  10. data/lib/active_record/connection_adapters/jdbc_adapter_spec.rb +10 -0
  11. data/lib/active_record/connection_adapters/jndi_adapter.rb +1 -0
  12. data/lib/active_record/connection_adapters/mysql_adapter.rb +13 -0
  13. data/lib/active_record/connection_adapters/oracle_adapter.rb +1 -0
  14. data/lib/active_record/connection_adapters/postgresql_adapter.rb +13 -0
  15. data/lib/jdbc_adapter.rb +32 -0
  16. data/lib/jdbc_adapter/jdbc_db2.rb +104 -0
  17. data/lib/jdbc_adapter/jdbc_derby.rb +362 -0
  18. data/lib/jdbc_adapter/jdbc_firebird.rb +109 -0
  19. data/lib/jdbc_adapter/jdbc_hsqldb.rb +168 -0
  20. data/lib/jdbc_adapter/jdbc_mimer.rb +134 -0
  21. data/lib/jdbc_adapter/jdbc_mssql.rb +356 -0
  22. data/lib/jdbc_adapter/jdbc_mysql.rb +168 -0
  23. data/lib/jdbc_adapter/jdbc_oracle.rb +340 -0
  24. data/lib/jdbc_adapter/jdbc_postgre.rb +347 -0
  25. data/lib/jdbc_adapter/missing_functionality_helper.rb +72 -0
  26. data/lib/jdbc_adapter/version.rb +5 -0
  27. data/lib/jdbc_adapter_internal.jar +0 -0
  28. data/lib/tasks/jdbc_databases.rake +72 -0
  29. data/src/java/JDBCDerbySpec.java +323 -0
  30. data/src/java/JDBCMySQLSpec.java +89 -0
  31. data/src/java/JdbcAdapterInternalService.java +953 -0
  32. data/test/activerecord/connection_adapters/type_conversion_test.rb +31 -0
  33. data/test/activerecord/connections/native_jdbc_mysql/connection.rb +25 -0
  34. data/test/db/derby.rb +18 -0
  35. data/test/db/h2.rb +11 -0
  36. data/test/db/hsqldb.rb +15 -0
  37. data/test/db/jdbc.rb +11 -0
  38. data/test/db/jndi_config.rb +30 -0
  39. data/test/db/logger.rb +3 -0
  40. data/test/db/mysql.rb +9 -0
  41. data/test/db/postgres.rb +9 -0
  42. data/test/derby_multibyte_test.rb +12 -0
  43. data/test/derby_simple_test.rb +12 -0
  44. data/test/generic_jdbc_connection_test.rb +9 -0
  45. data/test/h2_simple_test.rb +7 -0
  46. data/test/hsqldb_simple_test.rb +6 -0
  47. data/test/jdbc_adapter/jdbc_db2_test.rb +21 -0
  48. data/test/jdbc_common.rb +6 -0
  49. data/test/jndi_test.rb +37 -0
  50. data/test/manualTestDatabase.rb +195 -0
  51. data/test/minirunit.rb +109 -0
  52. data/test/minirunit/testConnect.rb +14 -0
  53. data/test/minirunit/testH2.rb +73 -0
  54. data/test/minirunit/testHsqldb.rb +73 -0
  55. data/test/minirunit/testLoadActiveRecord.rb +3 -0
  56. data/test/minirunit/testMysql.rb +83 -0
  57. data/test/minirunit/testRawSelect.rb +24 -0
  58. data/test/models/auto_id.rb +18 -0
  59. data/test/models/data_types.rb +18 -0
  60. data/test/models/entry.rb +20 -0
  61. data/test/mysql_multibyte_test.rb +6 -0
  62. data/test/mysql_simple_test.rb +13 -0
  63. data/test/postgres_simple_test.rb +12 -0
  64. data/test/simple.rb +157 -0
  65. metadata +112 -0
@@ -0,0 +1,10 @@
1
+
2
+ require 'jdbc_adapter/jdbc_mimer'
3
+ require 'jdbc_adapter/jdbc_hsqldb'
4
+ require 'jdbc_adapter/jdbc_oracle'
5
+ require 'jdbc_adapter/jdbc_postgre'
6
+ require 'jdbc_adapter/jdbc_mysql'
7
+ require 'jdbc_adapter/jdbc_derby'
8
+ require 'jdbc_adapter/jdbc_firebird'
9
+ require 'jdbc_adapter/jdbc_db2'
10
+ require 'jdbc_adapter/jdbc_mssql'
@@ -0,0 +1 @@
1
+ require 'active_record/connection_adapters/jdbc_adapter'
@@ -0,0 +1,13 @@
1
+ tried_gem = false
2
+ begin
3
+ require "jdbc/mysql"
4
+ rescue LoadError
5
+ unless tried_gem
6
+ require 'rubygems'
7
+ gem "jdbc-mysql"
8
+ tried_gem = true
9
+ retry
10
+ end
11
+ # trust that the mysql jar is already present
12
+ end
13
+ require 'active_record/connection_adapters/jdbc_adapter'
@@ -0,0 +1 @@
1
+ require 'active_record/connection_adapters/jdbc_adapter'
@@ -0,0 +1,13 @@
1
+ tried_gem = false
2
+ begin
3
+ require "jdbc/postgres"
4
+ rescue LoadError
5
+ unless tried_gem
6
+ require 'rubygems'
7
+ gem "jdbc-postgres"
8
+ tried_gem = true
9
+ retry
10
+ end
11
+ # trust that the postgres jar is already present
12
+ end
13
+ require 'active_record/connection_adapters/jdbc_adapter'
@@ -0,0 +1,32 @@
1
+ if RUBY_PLATFORM =~ /java/
2
+ begin
3
+ tried_gem ||= false
4
+ require 'active_record/version'
5
+ rescue LoadError
6
+ raise if tried_gem
7
+ require 'rubygems'
8
+ gem 'activerecord'
9
+ tried_gem = true
10
+ retry
11
+ end
12
+ if ActiveRecord::VERSION::MAJOR < 2
13
+ if defined?(RAILS_CONNECTION_ADAPTERS)
14
+ RAILS_CONNECTION_ADAPTERS << %q(jdbc)
15
+ else
16
+ RAILS_CONNECTION_ADAPTERS = %w(jdbc)
17
+ end
18
+ if ActiveRecord::VERSION::MAJOR == 1 && ActiveRecord::VERSION::MINOR == 14
19
+ require 'active_record/connection_adapters/jdbc_adapter'
20
+ end
21
+ end
22
+ if defined?(RAILS_ROOT)
23
+ to_file = File.expand_path(File.join(RAILS_ROOT, 'lib', 'tasks', 'jdbc_databases.rake'))
24
+ from_file = File.expand_path(File.join(File.dirname(__FILE__), 'tasks', 'jdbc_databases.rake'))
25
+ if !File.exist?(to_file) || (File.mtime(to_file) < File.mtime(from_file))
26
+ require 'fileutils'
27
+ FileUtils.cp from_file, to_file, :verbose => true
28
+ end
29
+ end
30
+ else
31
+ warn "ActiveRecord-JDBC is for use with JRuby only"
32
+ end
@@ -0,0 +1,104 @@
1
+ module JdbcSpec
2
+ module DB2
3
+ def self.column_selector
4
+ [/db2/i, lambda {|cfg,col|
5
+ if cfg[:url] =~ /^jdbc:derby:net:/
6
+ col.extend(::JdbcSpec::Derby::Column)
7
+ else
8
+ col.extend(::JdbcSpec::DB2::Column)
9
+ end }]
10
+ end
11
+
12
+ def self.adapter_selector
13
+ [/db2/i, lambda {|cfg,adapt|
14
+ if cfg[:url] =~ /^jdbc:derby:net:/
15
+ adapt.extend(::JdbcSpec::Derby)
16
+ else
17
+ adapt.extend(::JdbcSpec::DB2)
18
+ end }]
19
+ end
20
+
21
+ module Column
22
+ def type_cast(value)
23
+ return nil if value.nil? || value =~ /^\s*null\s*$/i
24
+ case type
25
+ when :string then value
26
+ when :integer then defined?(value.to_i) ? value.to_i : (value ? 1 : 0)
27
+ when :primary_key then defined?(value.to_i) ? value.to_i : (value ? 1 : 0)
28
+ when :float then value.to_f
29
+ when :datetime then cast_to_date_or_time(value)
30
+ when :timestamp then cast_to_time(value)
31
+ when :time then cast_to_time(value)
32
+ else value
33
+ end
34
+ end
35
+ def cast_to_date_or_time(value)
36
+ return value if value.is_a? Date
37
+ return nil if value.blank?
38
+ guess_date_or_time((value.is_a? Time) ? value : cast_to_time(value))
39
+ end
40
+
41
+ def cast_to_time(value)
42
+ return value if value.is_a? Time
43
+ time_array = ParseDate.parsedate value
44
+ time_array[0] ||= 2000; time_array[1] ||= 1; time_array[2] ||= 1;
45
+ Time.send(ActiveRecord::Base.default_timezone, *time_array) rescue nil
46
+ end
47
+
48
+ def guess_date_or_time(value)
49
+ (value.hour == 0 and value.min == 0 and value.sec == 0) ?
50
+ Date.new(value.year, value.month, value.day) : value
51
+ end
52
+ end
53
+
54
+ def modify_types(tp)
55
+ tp[:primary_key] = 'int generated by default as identity (start with 42) primary key'
56
+ tp[:string][:limit] = 255
57
+ tp[:integer][:limit] = nil
58
+ tp[:boolean][:limit] = nil
59
+ tp
60
+ end
61
+
62
+ def add_limit_offset!(sql, options)
63
+ if limit = options[:limit]
64
+ offset = options[:offset] || 0
65
+ sql.gsub!(/SELECT/i, 'SELECT B.* FROM (SELECT A.*, row_number() over () AS internal$rownum FROM (SELECT')
66
+ sql << ") A ) B WHERE B.internal$rownum > #{offset} AND B.internal$rownum <= #{limit + offset}"
67
+ end
68
+ end
69
+
70
+ def quote_column_name(column_name)
71
+ column_name
72
+ end
73
+
74
+ def quote(value, column = nil) # :nodoc:
75
+ if column && column.type == :primary_key
76
+ return value.to_s
77
+ end
78
+ if column && column.type == :decimal && value
79
+ return value.to_s
80
+ end
81
+ case value
82
+ when String
83
+ if column && column.type == :binary
84
+ "BLOB('#{quote_string(value)}')"
85
+ else
86
+ "'#{quote_string(value)}'"
87
+ end
88
+ else super
89
+ end
90
+ end
91
+
92
+ def quote_string(string)
93
+ string.gsub(/'/, "''") # ' (for ruby-mode)
94
+ end
95
+
96
+ def quoted_true
97
+ '1'
98
+ end
99
+
100
+ def quoted_false
101
+ '0'
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,362 @@
1
+ require 'jdbc_adapter/missing_functionality_helper'
2
+
3
+ module ::JdbcSpec
4
+ module ActiveRecordExtensions
5
+ def derby_connection(config)
6
+ config[:url] ||= "jdbc:derby:#{config[:database]};create=true"
7
+ config[:driver] ||= "org.apache.derby.jdbc.EmbeddedDriver"
8
+ embedded_driver(config)
9
+ end
10
+ end
11
+
12
+ module Derby
13
+ def self.column_selector
14
+ [/derby/i, lambda {|cfg,col| col.extend(::JdbcSpec::Derby::Column)}]
15
+ end
16
+
17
+ def self.adapter_selector
18
+ [/derby/i, lambda {|cfg,adapt| adapt.extend(::JdbcSpec::Derby)}]
19
+ end
20
+
21
+ def self.monkey_rails
22
+ unless @already_monkeyd
23
+ # Needed because Rails is broken wrt to quoting of
24
+ # some values. Most databases are nice about it,
25
+ # but not Derby. The real issue is that you can't
26
+ # compare a CHAR value to a NUMBER column.
27
+ ::ActiveRecord::Associations::ClassMethods.module_eval do
28
+ private
29
+
30
+ def select_limited_ids_list(options, join_dependency)
31
+ connection.select_all(
32
+ construct_finder_sql_for_association_limiting(options, join_dependency),
33
+ "#{name} Load IDs For Limited Eager Loading"
34
+ ).collect { |row| connection.quote(row[primary_key], columns_hash[primary_key]) }.join(", ")
35
+ end
36
+ end
37
+
38
+ @already_monkeyd = true
39
+ end
40
+ end
41
+
42
+ def self.extended(*args)
43
+ monkey_rails
44
+ end
45
+
46
+ def self.included(*args)
47
+ monkey_rails
48
+ end
49
+
50
+ module Column
51
+ def value_to_binary(value)
52
+ value.scan(/[0-9A-Fa-f]{2}/).collect {|v| v.to_i(16)}.pack("C*")
53
+ end
54
+
55
+ def cast_to_date_or_time(value)
56
+ return value if value.is_a? Date
57
+ return nil if value.blank?
58
+ guess_date_or_time((value.is_a? Time) ? value : cast_to_time(value))
59
+ end
60
+
61
+ def cast_to_time(value)
62
+ return value if value.is_a? Time
63
+ time_array = ParseDate.parsedate value
64
+ time_array[0] ||= 2000; time_array[1] ||= 1; time_array[2] ||= 1;
65
+ Time.send(ActiveRecord::Base.default_timezone, *time_array) rescue nil
66
+ end
67
+
68
+ def guess_date_or_time(value)
69
+ (value.hour == 0 and value.min == 0 and value.sec == 0) ?
70
+ Date.new(value.year, value.month, value.day) : value
71
+ end
72
+
73
+ def simplified_type(field_type)
74
+ return :boolean if field_type =~ /smallint/i
75
+ return :float if field_type =~ /real/i
76
+ super
77
+ end
78
+ end
79
+
80
+ include JdbcSpec::MissingFunctionalityHelper
81
+
82
+ def modify_types(tp)
83
+ tp[:primary_key] = "int generated by default as identity NOT NULL PRIMARY KEY"
84
+ tp[:integer][:limit] = nil
85
+ tp[:string][:limit] = 256
86
+ tp[:boolean] = {:name => "smallint"}
87
+ tp
88
+ end
89
+
90
+ def classes_for_table_name(table)
91
+ ActiveRecord::Base.send(:subclasses).select {|klass| klass.table_name == table}
92
+ end
93
+
94
+ # Set the sequence to the max value of the table's column.
95
+ def reset_sequence!(table, column, sequence = nil)
96
+ mpk = select_value("SELECT MAX(#{quote_column_name column}) FROM #{table}")
97
+ execute("ALTER TABLE #{table} ALTER COLUMN #{quote_column_name column} RESTART WITH #{mpk.to_i + 1}")
98
+ end
99
+
100
+ def reset_pk_sequence!(table, pk = nil, sequence = nil)
101
+ klasses = classes_for_table_name(table)
102
+ klass = klasses.nil? ? nil : klasses.first
103
+ pk = klass.primary_key unless klass.nil?
104
+ if pk && klass.columns_hash[pk].type == :integer
105
+ reset_sequence!(klass.table_name, pk)
106
+ end
107
+ end
108
+
109
+ def primary_key(table_name) #:nodoc:
110
+ primary_keys(table_name).first
111
+ end
112
+
113
+ def remove_index(table_name, options) #:nodoc:
114
+ execute "DROP INDEX #{index_name(table_name, options)}"
115
+ end
116
+
117
+ def rename_table(name, new_name)
118
+ execute "RENAME TABLE #{name} TO #{new_name}"
119
+ end
120
+
121
+ COLUMN_INFO_STMT = "SELECT C.COLUMNNAME, C.REFERENCEID, C.COLUMNNUMBER FROM SYS.SYSCOLUMNS C, SYS.SYSTABLES T WHERE T.TABLEID = '%s' AND T.TABLEID = C.REFERENCEID ORDER BY C.COLUMNNUMBER"
122
+
123
+ COLUMN_TYPE_STMT = "SELECT COLUMNDATATYPE, COLUMNDEFAULT FROM SYS.SYSCOLUMNS WHERE REFERENCEID = '%s' AND COLUMNNAME = '%s'"
124
+
125
+ AUTO_INC_STMT = "SELECT AUTOINCREMENTSTART, AUTOINCREMENTINC, COLUMNNAME, REFERENCEID, COLUMNDEFAULT FROM SYS.SYSCOLUMNS WHERE REFERENCEID = '%s' AND COLUMNNAME = '%s'"
126
+ AUTO_INC_STMT2 = "SELECT AUTOINCREMENTSTART, AUTOINCREMENTINC, COLUMNNAME, REFERENCEID, COLUMNDEFAULT FROM SYS.SYSCOLUMNS WHERE REFERENCEID = (SELECT T.TABLEID FROM SYS.SYSTABLES T WHERE T.TABLENAME = '%s') AND COLUMNNAME = '%s'"
127
+
128
+ def add_quotes(name)
129
+ return name unless name
130
+ %Q{"#{name}"}
131
+ end
132
+
133
+ def strip_quotes(str)
134
+ return str unless str
135
+ return str unless /^(["']).*\1$/ =~ str
136
+ str[1..-2]
137
+ end
138
+
139
+ def expand_double_quotes(name)
140
+ return name unless name && name['"']
141
+ name.gsub(/"/,'""')
142
+ end
143
+
144
+ def reinstate_auto_increment(name, refid, coldef)
145
+ stmt = AUTO_INC_STMT % [refid, strip_quotes(name)]
146
+ data = execute(stmt).first
147
+ if data
148
+ start = data['autoincrementstart']
149
+ if start
150
+ coldef << " GENERATED " << (data['columndefault'].nil? ? "ALWAYS" : "BY DEFAULT ")
151
+ coldef << "AS IDENTITY (START WITH "
152
+ coldef << start
153
+ coldef << ", INCREMENT BY "
154
+ coldef << data['autoincrementinc']
155
+ coldef << ")"
156
+ return true
157
+ end
158
+ end
159
+ false
160
+ end
161
+
162
+ def reinstate_auto_increment(name, refid, coldef)
163
+ stmt = AUTO_INC_STMT % [refid, strip_quotes(name)]
164
+ data = execute(stmt).first
165
+ if data
166
+ start = data['autoincrementstart']
167
+ if start
168
+ coldef << " GENERATED " << (data['columndefault'].nil? ? "ALWAYS" : "BY DEFAULT ")
169
+ coldef << "AS IDENTITY (START WITH "
170
+ coldef << start
171
+ coldef << ", INCREMENT BY "
172
+ coldef << data['autoincrementinc']
173
+ coldef << ")"
174
+ return true
175
+ end
176
+ end
177
+ false
178
+ end
179
+
180
+ def auto_increment_stmt(tname, cname)
181
+ stmt = AUTO_INC_STMT2 % [tname, strip_quotes(cname)]
182
+ data = execute(stmt).first
183
+ if data
184
+ start = data['autoincrementstart']
185
+ if start
186
+ coldef = ""
187
+ coldef << " GENERATED " << (data['columndefault'].nil? ? "ALWAYS" : "BY DEFAULT ")
188
+ coldef << "AS IDENTITY (START WITH "
189
+ coldef << start
190
+ coldef << ", INCREMENT BY "
191
+ coldef << data['autoincrementinc']
192
+ coldef << ")"
193
+ return coldef
194
+ end
195
+ end
196
+ ""
197
+ end
198
+
199
+ def create_column(name, refid, colno)
200
+ stmt = COLUMN_TYPE_STMT % [refid, strip_quotes(name)]
201
+ coldef = ""
202
+ data = execute(stmt).first
203
+ if data
204
+ coldef << add_quotes(expand_double_quotes(strip_quotes(name)))
205
+ coldef << " "
206
+ coldef << data['columndatatype']
207
+ if !reinstate_auto_increment(name, refid, coldef) && data['columndefault']
208
+ coldef << " DEFAULT " << data['columndefault']
209
+ end
210
+ end
211
+ coldef
212
+ end
213
+
214
+ SIZEABLE = %w(VARCHAR CLOB BLOB)
215
+
216
+ def structure_dump #:nodoc:
217
+ definition=""
218
+ rs = @connection.connection.meta_data.getTables(nil,nil,nil,["TABLE"].to_java(:string))
219
+ while rs.next
220
+ tname = rs.getString(3)
221
+ definition << "CREATE TABLE #{tname} (\n"
222
+ rs2 = @connection.connection.meta_data.getColumns(nil,nil,tname,nil)
223
+ first_col = true
224
+ while rs2.next
225
+ col_name = add_quotes(rs2.getString(4));
226
+ default = ""
227
+ d1 = rs2.getString(13)
228
+ if d1 =~ /^GENERATED_/
229
+ default = auto_increment_stmt(tname, col_name)
230
+ elsif d1
231
+ default = " DEFAULT #{d1}"
232
+ end
233
+
234
+ type = rs2.getString(6)
235
+ col_size = rs2.getString(7)
236
+ nulling = (rs2.getString(18) == 'NO' ? " NOT NULL" : "")
237
+ create_col_string = add_quotes(expand_double_quotes(strip_quotes(col_name))) +
238
+ " " +
239
+ type +
240
+ (SIZEABLE.include?(type) ? "(#{col_size})" : "") +
241
+ nulling +
242
+ default
243
+ if !first_col
244
+ create_col_string = ",\n #{create_col_string}"
245
+ else
246
+ create_col_string = " #{create_col_string}"
247
+ end
248
+
249
+ definition << create_col_string
250
+
251
+ first_col = false
252
+ end
253
+ definition << ");\n\n"
254
+ end
255
+ definition
256
+ end
257
+
258
+ # Support for removing columns added via derby bug issue:
259
+ # https://issues.apache.org/jira/browse/DERBY-1489
260
+ #
261
+ # This feature has not made it into a formal release and is not in Java 6.
262
+ # If the normal strategy fails we fall back on a strategy by creating a new
263
+ # table without the new column and there after moving the data to the new
264
+ #
265
+ def remove_column(table_name, column_name)
266
+ begin
267
+ execute "ALTER TABLE #{table_name} DROP COLUMN #{column_name} RESTRICT"
268
+ rescue
269
+ alter_table(table_name) do |definition|
270
+ definition.columns.delete(definition[column_name])
271
+ end
272
+ end
273
+ end
274
+
275
+ # Notes about changing in Derby:
276
+ # http://db.apache.org/derby/docs/10.2/ref/rrefsqlj81859.html#rrefsqlj81859__rrefsqlj37860)
277
+ #
278
+ # We support changing columns using the strategy outlined in:
279
+ # https://issues.apache.org/jira/browse/DERBY-1515
280
+ #
281
+ # This feature has not made it into a formal release and is not in Java 6. We will
282
+ # need to conditionally support this somehow (supposed to arrive for 10.3.0.0)
283
+ def change_column(table_name, column_name, type, options = {})
284
+ # null/not nulling is easy, handle that separately
285
+ if options.include?(:null)
286
+ # This seems to only work with 10.2 of Derby
287
+ if options.delete(:null) == false
288
+ execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} NOT NULL"
289
+ else
290
+ execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} NULL"
291
+ end
292
+ end
293
+
294
+ # anything left to do?
295
+ unless options.empty?
296
+ begin
297
+ execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET DATA TYPE #{type_to_sql(type, options[:limit])}"
298
+ rescue
299
+ transaction do
300
+ temp_new_column_name = "#{column_name}_newtype"
301
+ # 1) ALTER TABLE t ADD COLUMN c1_newtype NEWTYPE;
302
+ add_column table_name, temp_new_column_name, type, options
303
+ # 2) UPDATE t SET c1_newtype = c1;
304
+ execute "UPDATE #{table_name} SET #{temp_new_column_name} = CAST(#{column_name} AS #{type_to_sql(type, options[:limit])})"
305
+ # 3) ALTER TABLE t DROP COLUMN c1;
306
+ remove_column table_name, column_name
307
+ # 4) ALTER TABLE t RENAME COLUMN c1_newtype to c1;
308
+ rename_column table_name, temp_new_column_name, column_name
309
+ end
310
+ end
311
+ end
312
+ end
313
+
314
+ # Support for renaming columns:
315
+ # https://issues.apache.org/jira/browse/DERBY-1490
316
+ #
317
+ # This feature is expect to arrive in version 10.3.0.0:
318
+ # http://wiki.apache.org/db-derby/DerbyTenThreeRelease)
319
+ #
320
+ def rename_column(table_name, column_name, new_column_name) #:nodoc:
321
+ begin
322
+ execute "ALTER TABLE #{table_name} ALTER RENAME COLUMN #{column_name} TO #{new_column_name}"
323
+ rescue
324
+ alter_table(table_name, :rename => {column_name => new_column_name})
325
+ end
326
+ end
327
+
328
+ def primary_keys(table_name)
329
+ @connection.primary_keys table_name.to_s.upcase
330
+ end
331
+
332
+ def recreate_database(db_name)
333
+ tables.each do |t|
334
+ drop_table t
335
+ end
336
+ end
337
+
338
+ # For DDL it appears you can quote "" column names, but in queries (like insert it errors out?)
339
+ def quote_column_name(name) #:nodoc:
340
+ if /^references$/i =~ name
341
+ %Q{"#{name.upcase}"}
342
+ elsif /[A-Z]/ =~ name && /[a-z]/ =~ name
343
+ %Q{"#{name}"}
344
+ elsif name =~ /\s/
345
+ %Q{"#{name.upcase}"}
346
+ elsif name =~ /^[_\d]/
347
+ %Q{"#{name.upcase}"}
348
+ else
349
+ name
350
+ end
351
+ end
352
+
353
+ def quoted_true
354
+ '1'
355
+ end
356
+
357
+ def quoted_false
358
+ '0'
359
+ end
360
+ end
361
+ end
362
+