cmoran92-activerecord-jdbc-adapter 1.2.1

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 (202) hide show
  1. data/.gitignore +22 -0
  2. data/.travis.yml +8 -0
  3. data/Gemfile +14 -0
  4. data/Gemfile.lock +42 -0
  5. data/History.txt +469 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.rdoc +199 -0
  8. data/Rakefile +60 -0
  9. data/activerecord-jdbc-adapter.gemspec +23 -0
  10. data/bench/bench_attributes.rb +13 -0
  11. data/bench/bench_attributes_new.rb +14 -0
  12. data/bench/bench_create.rb +12 -0
  13. data/bench/bench_find_all.rb +12 -0
  14. data/bench/bench_find_all_mt.rb +25 -0
  15. data/bench/bench_model.rb +85 -0
  16. data/bench/bench_new.rb +12 -0
  17. data/bench/bench_new_valid.rb +12 -0
  18. data/bench/bench_valid.rb +13 -0
  19. data/lib/active_record/connection_adapters/derby_adapter.rb +1 -0
  20. data/lib/active_record/connection_adapters/h2_adapter.rb +1 -0
  21. data/lib/active_record/connection_adapters/hsqldb_adapter.rb +1 -0
  22. data/lib/active_record/connection_adapters/informix_adapter.rb +1 -0
  23. data/lib/active_record/connection_adapters/jdbc_adapter.rb +1 -0
  24. data/lib/active_record/connection_adapters/jndi_adapter.rb +1 -0
  25. data/lib/active_record/connection_adapters/mssql_adapter.rb +1 -0
  26. data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -0
  27. data/lib/active_record/connection_adapters/mysql_adapter.rb +1 -0
  28. data/lib/active_record/connection_adapters/oracle_adapter.rb +1 -0
  29. data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -0
  30. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -0
  31. data/lib/activerecord-jdbc-adapter.rb +8 -0
  32. data/lib/arel/engines/sql/compilers/db2_compiler.rb +9 -0
  33. data/lib/arel/engines/sql/compilers/derby_compiler.rb +6 -0
  34. data/lib/arel/engines/sql/compilers/h2_compiler.rb +6 -0
  35. data/lib/arel/engines/sql/compilers/hsqldb_compiler.rb +15 -0
  36. data/lib/arel/engines/sql/compilers/jdbc_compiler.rb +6 -0
  37. data/lib/arel/engines/sql/compilers/mssql_compiler.rb +46 -0
  38. data/lib/arel/visitors/compat.rb +13 -0
  39. data/lib/arel/visitors/db2.rb +17 -0
  40. data/lib/arel/visitors/derby.rb +25 -0
  41. data/lib/arel/visitors/firebird.rb +24 -0
  42. data/lib/arel/visitors/hsqldb.rb +26 -0
  43. data/lib/arel/visitors/sql_server.rb +44 -0
  44. data/lib/arjdbc.rb +24 -0
  45. data/lib/arjdbc/db2.rb +2 -0
  46. data/lib/arjdbc/db2/adapter.rb +510 -0
  47. data/lib/arjdbc/derby.rb +7 -0
  48. data/lib/arjdbc/derby/adapter.rb +351 -0
  49. data/lib/arjdbc/derby/connection_methods.rb +19 -0
  50. data/lib/arjdbc/discover.rb +92 -0
  51. data/lib/arjdbc/firebird.rb +2 -0
  52. data/lib/arjdbc/firebird/adapter.rb +136 -0
  53. data/lib/arjdbc/h2.rb +4 -0
  54. data/lib/arjdbc/h2/adapter.rb +54 -0
  55. data/lib/arjdbc/h2/connection_methods.rb +13 -0
  56. data/lib/arjdbc/hsqldb.rb +4 -0
  57. data/lib/arjdbc/hsqldb/adapter.rb +184 -0
  58. data/lib/arjdbc/hsqldb/connection_methods.rb +15 -0
  59. data/lib/arjdbc/informix.rb +3 -0
  60. data/lib/arjdbc/informix/adapter.rb +138 -0
  61. data/lib/arjdbc/informix/connection_methods.rb +11 -0
  62. data/lib/arjdbc/jdbc.rb +2 -0
  63. data/lib/arjdbc/jdbc/adapter.rb +354 -0
  64. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  65. data/lib/arjdbc/jdbc/callbacks.rb +44 -0
  66. data/lib/arjdbc/jdbc/column.rb +47 -0
  67. data/lib/arjdbc/jdbc/compatibility.rb +51 -0
  68. data/lib/arjdbc/jdbc/connection.rb +134 -0
  69. data/lib/arjdbc/jdbc/connection_methods.rb +16 -0
  70. data/lib/arjdbc/jdbc/core_ext.rb +24 -0
  71. data/lib/arjdbc/jdbc/discover.rb +18 -0
  72. data/lib/arjdbc/jdbc/driver.rb +35 -0
  73. data/lib/arjdbc/jdbc/extension.rb +47 -0
  74. data/lib/arjdbc/jdbc/java.rb +14 -0
  75. data/lib/arjdbc/jdbc/jdbc.rake +131 -0
  76. data/lib/arjdbc/jdbc/missing_functionality_helper.rb +87 -0
  77. data/lib/arjdbc/jdbc/quoted_primary_key.rb +28 -0
  78. data/lib/arjdbc/jdbc/railtie.rb +9 -0
  79. data/lib/arjdbc/jdbc/rake_tasks.rb +10 -0
  80. data/lib/arjdbc/jdbc/require_driver.rb +16 -0
  81. data/lib/arjdbc/jdbc/type_converter.rb +126 -0
  82. data/lib/arjdbc/mimer.rb +2 -0
  83. data/lib/arjdbc/mimer/adapter.rb +142 -0
  84. data/lib/arjdbc/mssql.rb +4 -0
  85. data/lib/arjdbc/mssql/adapter.rb +468 -0
  86. data/lib/arjdbc/mssql/connection_methods.rb +31 -0
  87. data/lib/arjdbc/mssql/limit_helpers.rb +108 -0
  88. data/lib/arjdbc/mssql/tsql_helper.rb +61 -0
  89. data/lib/arjdbc/mysql.rb +4 -0
  90. data/lib/arjdbc/mysql/adapter.rb +505 -0
  91. data/lib/arjdbc/mysql/connection_methods.rb +28 -0
  92. data/lib/arjdbc/oracle.rb +3 -0
  93. data/lib/arjdbc/oracle/adapter.rb +428 -0
  94. data/lib/arjdbc/oracle/connection_methods.rb +12 -0
  95. data/lib/arjdbc/postgresql.rb +4 -0
  96. data/lib/arjdbc/postgresql/adapter.rb +825 -0
  97. data/lib/arjdbc/postgresql/connection_methods.rb +23 -0
  98. data/lib/arjdbc/sqlite3.rb +4 -0
  99. data/lib/arjdbc/sqlite3/adapter.rb +387 -0
  100. data/lib/arjdbc/sqlite3/connection_methods.rb +35 -0
  101. data/lib/arjdbc/sybase.rb +2 -0
  102. data/lib/arjdbc/sybase/adapter.rb +46 -0
  103. data/lib/arjdbc/version.rb +8 -0
  104. data/lib/generators/jdbc/USAGE +10 -0
  105. data/lib/generators/jdbc/jdbc_generator.rb +9 -0
  106. data/lib/jdbc_adapter.rb +2 -0
  107. data/lib/jdbc_adapter/rake_tasks.rb +3 -0
  108. data/lib/jdbc_adapter/version.rb +3 -0
  109. data/lib/pg.rb +26 -0
  110. data/pom.xml +57 -0
  111. data/rails_generators/jdbc_generator.rb +15 -0
  112. data/rails_generators/templates/config/initializers/jdbc.rb +7 -0
  113. data/rails_generators/templates/lib/tasks/jdbc.rake +8 -0
  114. data/rakelib/bundler_ext.rb +11 -0
  115. data/rakelib/compile.rake +23 -0
  116. data/rakelib/db.rake +39 -0
  117. data/rakelib/rails.rake +41 -0
  118. data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +62 -0
  119. data/src/java/arjdbc/derby/DerbyModule.java +324 -0
  120. data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +70 -0
  121. data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +74 -0
  122. data/src/java/arjdbc/jdbc/AdapterJavaService.java +68 -0
  123. data/src/java/arjdbc/jdbc/JdbcConnectionFactory.java +36 -0
  124. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +1331 -0
  125. data/src/java/arjdbc/jdbc/SQLBlock.java +48 -0
  126. data/src/java/arjdbc/mssql/MssqlRubyJdbcConnection.java +127 -0
  127. data/src/java/arjdbc/mysql/MySQLModule.java +134 -0
  128. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +161 -0
  129. data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +85 -0
  130. data/src/java/arjdbc/postgresql/PostgresqlRubyJdbcConnection.java +82 -0
  131. data/src/java/arjdbc/sqlite3/Sqlite3RubyJdbcConnection.java +126 -0
  132. data/test/abstract_db_create.rb +135 -0
  133. data/test/activerecord/connection_adapters/type_conversion_test.rb +31 -0
  134. data/test/activerecord/connections/native_jdbc_mysql/connection.rb +25 -0
  135. data/test/activerecord/jall.sh +7 -0
  136. data/test/activerecord/jtest.sh +3 -0
  137. data/test/db/db2.rb +11 -0
  138. data/test/db/derby.rb +12 -0
  139. data/test/db/h2.rb +11 -0
  140. data/test/db/hsqldb.rb +13 -0
  141. data/test/db/informix.rb +11 -0
  142. data/test/db/jdbc.rb +12 -0
  143. data/test/db/jndi_config.rb +40 -0
  144. data/test/db/logger.rb +3 -0
  145. data/test/db/mssql.rb +9 -0
  146. data/test/db/mysql.rb +10 -0
  147. data/test/db/oracle.rb +34 -0
  148. data/test/db/postgres.rb +9 -0
  149. data/test/db/sqlite3.rb +11 -0
  150. data/test/db2_simple_test.rb +66 -0
  151. data/test/derby_migration_test.rb +68 -0
  152. data/test/derby_multibyte_test.rb +12 -0
  153. data/test/derby_simple_test.rb +99 -0
  154. data/test/generic_jdbc_connection_test.rb +29 -0
  155. data/test/h2_change_column_test.rb +68 -0
  156. data/test/h2_simple_test.rb +41 -0
  157. data/test/has_many_through.rb +79 -0
  158. data/test/helper.rb +85 -0
  159. data/test/hsqldb_simple_test.rb +6 -0
  160. data/test/informix_simple_test.rb +48 -0
  161. data/test/jdbc_common.rb +27 -0
  162. data/test/jndi_callbacks_test.rb +40 -0
  163. data/test/jndi_test.rb +25 -0
  164. data/test/manualTestDatabase.rb +191 -0
  165. data/test/models/add_not_null_column_to_table.rb +9 -0
  166. data/test/models/auto_id.rb +15 -0
  167. data/test/models/data_types.rb +30 -0
  168. data/test/models/entry.rb +40 -0
  169. data/test/models/mixed_case.rb +22 -0
  170. data/test/models/reserved_word.rb +15 -0
  171. data/test/models/string_id.rb +17 -0
  172. data/test/models/thing.rb +16 -0
  173. data/test/models/validates_uniqueness_of_string.rb +19 -0
  174. data/test/mssql_db_create_test.rb +26 -0
  175. data/test/mssql_identity_insert_test.rb +19 -0
  176. data/test/mssql_legacy_types_test.rb +58 -0
  177. data/test/mssql_limit_offset_test.rb +136 -0
  178. data/test/mssql_multibyte_test.rb +18 -0
  179. data/test/mssql_simple_test.rb +55 -0
  180. data/test/mysql_db_create_test.rb +27 -0
  181. data/test/mysql_index_length_test.rb +58 -0
  182. data/test/mysql_info_test.rb +123 -0
  183. data/test/mysql_multibyte_test.rb +10 -0
  184. data/test/mysql_nonstandard_primary_key_test.rb +42 -0
  185. data/test/mysql_simple_test.rb +125 -0
  186. data/test/oracle_simple_test.rb +18 -0
  187. data/test/oracle_specific_test.rb +83 -0
  188. data/test/postgres_db_create_test.rb +32 -0
  189. data/test/postgres_drop_db_test.rb +16 -0
  190. data/test/postgres_information_schema_leak_test.rb +29 -0
  191. data/test/postgres_mixed_case_test.rb +29 -0
  192. data/test/postgres_native_type_mapping_test.rb +89 -0
  193. data/test/postgres_nonseq_pkey_test.rb +38 -0
  194. data/test/postgres_reserved_test.rb +22 -0
  195. data/test/postgres_schema_search_path_test.rb +48 -0
  196. data/test/postgres_simple_test.rb +167 -0
  197. data/test/postgres_table_alias_length_test.rb +15 -0
  198. data/test/postgres_type_conversion_test.rb +34 -0
  199. data/test/simple.rb +658 -0
  200. data/test/sqlite3_simple_test.rb +284 -0
  201. data/test/sybase_jtds_simple_test.rb +28 -0
  202. metadata +261 -0
@@ -0,0 +1,7 @@
1
+ require 'arjdbc/jdbc'
2
+ jdbc_require_driver 'jdbc/derby'
3
+ require 'arjdbc/derby/connection_methods'
4
+ require 'arjdbc/derby/adapter'
5
+
6
+
7
+
@@ -0,0 +1,351 @@
1
+ require 'arjdbc/jdbc/missing_functionality_helper'
2
+
3
+ module ::ArJdbc
4
+ module Derby
5
+ def self.column_selector
6
+ [/derby/i, lambda {|cfg,col| col.extend(::ArJdbc::Derby::Column)}]
7
+ end
8
+
9
+ def self.monkey_rails
10
+ unless defined?(@already_monkeyd)
11
+ # Needed because Rails is broken wrt to quoting of
12
+ # some values. Most databases are nice about it,
13
+ # but not Derby. The real issue is that you can't
14
+ # compare a CHAR value to a NUMBER column.
15
+ ::ActiveRecord::Associations::ClassMethods.module_eval do
16
+ private
17
+
18
+ def select_limited_ids_list(options, join_dependency)
19
+ connection.select_all(
20
+ construct_finder_sql_for_association_limiting(options, join_dependency),
21
+ "#{name} Load IDs For Limited Eager Loading"
22
+ ).collect { |row| connection.quote(row[primary_key], columns_hash[primary_key]) }.join(", ")
23
+ end
24
+ end
25
+
26
+ @already_monkeyd = true
27
+ end
28
+ end
29
+
30
+ def self.extended(*args)
31
+ monkey_rails
32
+ end
33
+
34
+ def self.included(*args)
35
+ monkey_rails
36
+ end
37
+
38
+ module Column
39
+ def simplified_type(field_type)
40
+ case field_type
41
+ when /smallint/i then :boolean
42
+ when /real/i then :float
43
+ else
44
+ super
45
+ end
46
+ end
47
+
48
+ # Post process default value from JDBC into a Rails-friendly format (columns{-internal})
49
+ def default_value(value)
50
+ # jdbc returns column default strings with actual single quotes around the value.
51
+ return $1 if value =~ /^'(.*)'$/
52
+ return nil if value == "GENERATED_BY_DEFAULT"
53
+ value
54
+ end
55
+ end
56
+
57
+ def adapter_name #:nodoc:
58
+ 'Derby'
59
+ end
60
+
61
+ def self.arel2_visitors(config)
62
+ require 'arel/visitors/derby'
63
+ {}.tap {|v| %w(derby jdbcderby).each {|a| v[a] = ::Arel::Visitors::Derby } }
64
+ end
65
+
66
+ include ArJdbc::MissingFunctionalityHelper
67
+
68
+ def index_name_length
69
+ 128
70
+ end
71
+
72
+ # Convert the specified column type to a SQL string.
73
+ # In Derby, the following cannot specify a limit:
74
+ # - integer
75
+ # - boolean (smallint)
76
+ # - timestamp
77
+ # - date
78
+ def type_to_sql(type, limit = nil, precision = nil, scale = nil) #:nodoc:
79
+ return super unless [:integer, :boolean, :timestamp, :date].include? type
80
+
81
+ native = native_database_types[type.to_s.downcase.to_sym]
82
+ native.is_a?(Hash) ? native[:name] : native
83
+ end
84
+
85
+ def modify_types(tp)
86
+ tp[:primary_key] = "int generated by default as identity NOT NULL PRIMARY KEY"
87
+ tp[:string][:limit] = 256
88
+ tp[:integer][:limit] = nil
89
+ tp[:boolean] = {:name => "smallint"}
90
+ tp[:timestamp][:limit] = nil
91
+ tp[:date][:limit] = nil
92
+ tp
93
+ end
94
+
95
+ # Override default -- fix case where ActiveRecord passes :default => nil, :null => true
96
+ def add_column_options!(sql, options)
97
+ options.delete(:default) if options.has_key?(:default) && options[:default].nil?
98
+ sql << " DEFAULT #{quote(options.delete(:default))}" if options.has_key?(:default)
99
+ super
100
+ end
101
+
102
+ def classes_for_table_name(table)
103
+ ActiveRecord::Base.send(:subclasses).select {|klass| klass.table_name == table}
104
+ end
105
+
106
+ # Set the sequence to the max value of the table's column.
107
+ def reset_sequence!(table, column, sequence = nil)
108
+ mpk = select_value("SELECT MAX(#{quote_column_name(column)}) FROM #{quote_table_name(table)}")
109
+ execute("ALTER TABLE #{quote_table_name(table)} ALTER COLUMN #{quote_column_name(column)} RESTART WITH #{mpk.to_i + 1}")
110
+ end
111
+
112
+ def reset_pk_sequence!(table, pk = nil, sequence = nil)
113
+ klasses = classes_for_table_name(table)
114
+ klass = klasses.nil? ? nil : klasses.first
115
+ pk = klass.primary_key unless klass.nil?
116
+ if pk && klass.columns_hash[pk].type == :integer
117
+ reset_sequence!(klass.table_name, pk)
118
+ end
119
+ end
120
+
121
+ def remove_index(table_name, options) #:nodoc:
122
+ execute "DROP INDEX #{index_name(table_name, options)}"
123
+ end
124
+
125
+ def rename_table(name, new_name)
126
+ execute "RENAME TABLE #{quote_table_name(name)} TO #{quote_table_name(new_name)}"
127
+ end
128
+
129
+ 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'"
130
+
131
+ def add_quotes(name)
132
+ return name unless name
133
+ %Q{"#{name}"}
134
+ end
135
+
136
+ def strip_quotes(str)
137
+ return str unless str
138
+ return str unless /^(["']).*\1$/ =~ str
139
+ str[1..-2]
140
+ end
141
+
142
+ def expand_double_quotes(name)
143
+ return name unless name && name['"']
144
+ name.gsub(/"/,'""')
145
+ end
146
+
147
+ def auto_increment_stmt(tname, cname)
148
+ stmt = AUTO_INC_STMT2 % [tname, strip_quotes(cname)]
149
+ data = execute(stmt).first
150
+ if data
151
+ start = data['autoincrementstart']
152
+ if start
153
+ coldef = ""
154
+ coldef << " GENERATED " << (data['columndefault'].nil? ? "ALWAYS" : "BY DEFAULT ")
155
+ coldef << "AS IDENTITY (START WITH "
156
+ coldef << start
157
+ coldef << ", INCREMENT BY "
158
+ coldef << data['autoincrementinc']
159
+ coldef << ")"
160
+ return coldef
161
+ end
162
+ end
163
+ ""
164
+ end
165
+
166
+
167
+ def add_column(table_name, column_name, type, options = {})
168
+ add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
169
+ add_column_options!(add_column_sql, options)
170
+ execute(add_column_sql)
171
+ end
172
+
173
+ def execute(sql, name = nil, binds = [])
174
+ sql = extract_sql(sql)
175
+ if sql =~ /\A\s*(UPDATE|INSERT)/i
176
+ i = sql =~ /\swhere\s/im
177
+ if i
178
+ sql[i..-1] = sql[i..-1].gsub(/!=\s*NULL/, 'IS NOT NULL').gsub(/=\sNULL/i, 'IS NULL')
179
+ end
180
+ else
181
+ sql.gsub!(/= NULL/i, 'IS NULL')
182
+ end
183
+ super
184
+ end
185
+
186
+ # SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause.
187
+ #
188
+ # Derby requires the ORDER BY columns in the select list for distinct queries, and
189
+ # requires that the ORDER BY include the distinct column.
190
+ #
191
+ # distinct("posts.id", "posts.created_at desc")
192
+ #
193
+ # Based on distinct method for PostgreSQL Adapter
194
+ def distinct(columns, order_by)
195
+ return "DISTINCT #{columns}" if order_by.blank?
196
+
197
+ # construct a clean list of column names from the ORDER BY clause, removing
198
+ # any asc/desc modifiers
199
+ order_columns = [order_by].flatten.map{|o| o.split(',').collect { |s| s.split.first } }.flatten.reject(&:blank?)
200
+ order_columns = order_columns.zip((0...order_columns.size).to_a).map { |s,i| "#{s} AS alias_#{i}" }
201
+
202
+ # return a DISTINCT clause that's distinct on the columns we want but includes
203
+ # all the required columns for the ORDER BY to work properly
204
+ sql = "DISTINCT #{columns}, #{order_columns * ', '}"
205
+ sql
206
+ end
207
+
208
+ SIZEABLE = %w(VARCHAR CLOB BLOB)
209
+
210
+ def structure_dump #:nodoc:
211
+ definition=""
212
+ rs = @connection.connection.meta_data.getTables(nil,nil,nil,["TABLE"].to_java(:string))
213
+ while rs.next
214
+ tname = rs.getString(3)
215
+ definition << "CREATE TABLE #{tname} (\n"
216
+ rs2 = @connection.connection.meta_data.getColumns(nil,nil,tname,nil)
217
+ first_col = true
218
+ while rs2.next
219
+ col_name = add_quotes(rs2.getString(4));
220
+ default = ""
221
+ d1 = rs2.getString(13)
222
+ if d1 =~ /^GENERATED_/
223
+ default = auto_increment_stmt(tname, col_name)
224
+ elsif d1
225
+ default = " DEFAULT #{d1}"
226
+ end
227
+
228
+ type = rs2.getString(6)
229
+ col_size = rs2.getString(7)
230
+ nulling = (rs2.getString(18) == 'NO' ? " NOT NULL" : "")
231
+ create_col_string = add_quotes(expand_double_quotes(strip_quotes(col_name))) +
232
+ " " +
233
+ type +
234
+ (SIZEABLE.include?(type) ? "(#{col_size})" : "") +
235
+ nulling +
236
+ default
237
+ if !first_col
238
+ create_col_string = ",\n #{create_col_string}"
239
+ else
240
+ create_col_string = " #{create_col_string}"
241
+ end
242
+
243
+ definition << create_col_string
244
+
245
+ first_col = false
246
+ end
247
+ definition << ");\n\n"
248
+ end
249
+ definition
250
+ end
251
+
252
+ def remove_column(table_name, column_name)
253
+ execute "ALTER TABLE #{quote_table_name(table_name)} DROP COLUMN #{quote_column_name(column_name)} RESTRICT"
254
+ end
255
+
256
+ # Notes about changing in Derby:
257
+ # http://db.apache.org/derby/docs/10.2/ref/rrefsqlj81859.html#rrefsqlj81859__rrefsqlj37860)
258
+ #
259
+ # We support changing columns using the strategy outlined in:
260
+ # https://issues.apache.org/jira/browse/DERBY-1515
261
+ #
262
+ # This feature has not made it into a formal release and is not in Java 6. We will
263
+ # need to conditionally support this somehow (supposed to arrive for 10.3.0.0)
264
+ def change_column(table_name, column_name, type, options = {})
265
+ # null/not nulling is easy, handle that separately
266
+ if options.include?(:null)
267
+ # This seems to only work with 10.2 of Derby
268
+ if options.delete(:null) == false
269
+ execute "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} NOT NULL"
270
+ else
271
+ execute "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} NULL"
272
+ end
273
+ end
274
+
275
+ # anything left to do?
276
+ unless options.empty?
277
+ begin
278
+ execute "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} SET DATA TYPE #{type_to_sql(type, options[:limit])}"
279
+ rescue
280
+ transaction do
281
+ temp_new_column_name = "#{column_name}_newtype"
282
+ # 1) ALTER TABLE t ADD COLUMN c1_newtype NEWTYPE;
283
+ add_column table_name, temp_new_column_name, type, options
284
+ # 2) UPDATE t SET c1_newtype = c1;
285
+ execute "UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(temp_new_column_name)} = CAST(#{quote_column_name(column_name)} AS #{type_to_sql(type, options[:limit])})"
286
+ # 3) ALTER TABLE t DROP COLUMN c1;
287
+ remove_column table_name, column_name
288
+ # 4) ALTER TABLE t RENAME COLUMN c1_newtype to c1;
289
+ rename_column table_name, temp_new_column_name, column_name
290
+ end
291
+ end
292
+ end
293
+ end
294
+
295
+ def rename_column(table_name, column_name, new_column_name) #:nodoc:
296
+ execute "RENAME COLUMN #{quote_table_name(table_name)}.#{quote_column_name(column_name)} TO #{quote_column_name(new_column_name)}"
297
+ end
298
+
299
+ def primary_keys(table_name)
300
+ @connection.primary_keys table_name.to_s.upcase
301
+ end
302
+
303
+ def columns(table_name, name=nil)
304
+ @connection.columns_internal(table_name.to_s, name, derby_schema)
305
+ end
306
+
307
+ def tables
308
+ @connection.tables(nil, derby_schema)
309
+ end
310
+
311
+ def recreate_database(db_name)
312
+ tables.each do |t|
313
+ drop_table t
314
+ end
315
+ end
316
+
317
+ def quote_column_name(name) #:nodoc:
318
+ %Q{"#{name.to_s.upcase.gsub(/\"/, '""')}"}
319
+ end
320
+
321
+ def quoted_true
322
+ '1'
323
+ end
324
+
325
+ def quoted_false
326
+ '0'
327
+ end
328
+
329
+ def add_limit_offset!(sql, options) #:nodoc:
330
+ if options[:offset]
331
+ sql << " OFFSET #{options[:offset]} ROWS"
332
+ end
333
+ if options[:limit]
334
+ #ROWS/ROW and FIRST/NEXT mean the same
335
+ sql << " FETCH FIRST #{options[:limit]} ROWS ONLY"
336
+ end
337
+ end
338
+
339
+ private
340
+ # Derby appears to define schemas using the username
341
+ def derby_schema
342
+ if @config.has_key?(:schema)
343
+ config[:schema]
344
+ else
345
+ (@config[:username] && @config[:username].to_s) || ''
346
+ end
347
+ end
348
+ end
349
+ end
350
+
351
+
@@ -0,0 +1,19 @@
1
+ module ActiveRecord
2
+ class Base
3
+ class << self
4
+ def derby_connection(config)
5
+ config[:url] ||= "jdbc:derby:#{config[:database]};create=true"
6
+ config[:driver] ||= "org.apache.derby.jdbc.EmbeddedDriver"
7
+ config[:adapter_spec] = ::ArJdbc::Derby
8
+ conn = embedded_driver(config)
9
+ md = conn.jdbc_connection.meta_data
10
+ if md.database_major_version < 10 || (md.database_major_version == 10 && md.database_minor_version < 5)
11
+ raise ::ActiveRecord::ConnectionFailed, "Derby adapter requires Derby 10.5 or later"
12
+ end
13
+ conn
14
+ end
15
+
16
+ alias_method :jdbcderby_connection, :derby_connection
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,92 @@
1
+ # arjdbc/discover.rb: Declare ArJdbc.extension modules in this file
2
+ # that loads a custom module and adapter.
3
+
4
+ module ::ArJdbc
5
+ # Adapters built-in to AR are required up-front so we can override
6
+ # the native ones
7
+ require 'arjdbc/mysql'
8
+ extension :MySQL do |name|
9
+ name =~ /mysql/i
10
+ end
11
+
12
+ require 'arjdbc/postgresql'
13
+ extension :PostgreSQL do |name|
14
+ name =~ /postgre/i
15
+ end
16
+
17
+ require 'arjdbc/sqlite3'
18
+ extension :SQLite3 do |name|
19
+ name =~ /sqlite/i
20
+ end
21
+
22
+ # Other adapters are lazy-loaded
23
+ extension :DB2 do |name, config|
24
+ if name =~ /(db2|as400)/i && config[:url] !~ /^jdbc:derby:net:/
25
+ require 'arjdbc/db2'
26
+ true
27
+ end
28
+ end
29
+
30
+ extension :Derby do |name|
31
+ if name =~ /derby/i
32
+ require 'arjdbc/derby'
33
+ true
34
+ end
35
+ end
36
+
37
+ extension :FireBird do |name|
38
+ if name =~ /firebird/i
39
+ require 'arjdbc/firebird'
40
+ true
41
+ end
42
+ end
43
+
44
+ extension :H2 do |name|
45
+ if name =~ /\.h2\./i
46
+ require 'arjdbc/h2'
47
+ true
48
+ end
49
+ end
50
+
51
+ extension :HSQLDB do |name|
52
+ if name =~ /hsqldb/i
53
+ require 'arjdbc/hsqldb'
54
+ true
55
+ end
56
+ end
57
+
58
+ extension :Informix do |name|
59
+ if name =~ /informix/i
60
+ require 'arjdbc/informix'
61
+ true
62
+ end
63
+ end
64
+
65
+ extension :Mimer do |name|
66
+ if name =~ /mimer/i
67
+ require 'arjdbc/mimer'
68
+ true
69
+ end
70
+ end
71
+
72
+ extension :MsSQL do |name|
73
+ if name =~ /sqlserver|tds|Microsoft SQL/i
74
+ require 'arjdbc/mssql'
75
+ true
76
+ end
77
+ end
78
+
79
+ extension :Oracle do |name|
80
+ if name =~ /oracle/i
81
+ require 'arjdbc/oracle'
82
+ true
83
+ end
84
+ end
85
+
86
+ extension :Sybase do |name|
87
+ if name =~ /sybase|tds/i
88
+ require 'arjdbc/sybase'
89
+ true
90
+ end
91
+ end
92
+ end