activerecord-jdbc-adapter 1.2.5 → 1.2.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. data/.gitignore +1 -0
  2. data/.travis.yml +5 -1
  3. data/Appraisals +5 -5
  4. data/Gemfile +9 -1
  5. data/Gemfile.lock +44 -10
  6. data/History.txt +126 -2
  7. data/README.md +246 -0
  8. data/Rakefile +34 -25
  9. data/activerecord-jdbc-adapter.gemspec +1 -1
  10. data/gemfiles/rails23.gemfile +5 -3
  11. data/gemfiles/rails23.gemfile.lock +26 -18
  12. data/gemfiles/rails30.gemfile +4 -2
  13. data/gemfiles/rails30.gemfile.lock +16 -8
  14. data/gemfiles/rails31.gemfile +4 -2
  15. data/gemfiles/rails31.gemfile.lock +16 -9
  16. data/gemfiles/rails32.gemfile +4 -2
  17. data/gemfiles/rails32.gemfile.lock +15 -8
  18. data/lib/active_record/connection_adapters/db2_adapter.rb +1 -0
  19. data/lib/arel/visitors/sql_server.rb +3 -0
  20. data/lib/arjdbc.rb +3 -5
  21. data/lib/arjdbc/db2.rb +1 -0
  22. data/lib/arjdbc/db2/adapter.rb +302 -196
  23. data/lib/arjdbc/db2/connection_methods.rb +18 -0
  24. data/lib/arjdbc/derby/active_record_patch.rb +12 -0
  25. data/lib/arjdbc/derby/adapter.rb +180 -158
  26. data/lib/arjdbc/derby/connection_methods.rb +5 -1
  27. data/lib/arjdbc/firebird/adapter.rb +27 -19
  28. data/lib/arjdbc/h2/adapter.rb +162 -7
  29. data/lib/arjdbc/h2/connection_methods.rb +5 -1
  30. data/lib/arjdbc/hsqldb.rb +1 -1
  31. data/lib/arjdbc/hsqldb/adapter.rb +96 -61
  32. data/lib/arjdbc/hsqldb/connection_methods.rb +5 -1
  33. data/lib/arjdbc/hsqldb/explain_support.rb +35 -0
  34. data/lib/arjdbc/informix/adapter.rb +56 -55
  35. data/lib/arjdbc/jdbc/adapter.rb +173 -86
  36. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  37. data/lib/arjdbc/jdbc/column.rb +28 -23
  38. data/lib/arjdbc/jdbc/connection.rb +10 -6
  39. data/lib/arjdbc/jdbc/driver.rb +13 -5
  40. data/lib/arjdbc/jdbc/serialized_attributes_helper.rb +21 -0
  41. data/lib/arjdbc/mssql.rb +1 -1
  42. data/lib/arjdbc/mssql/adapter.rb +51 -53
  43. data/lib/arjdbc/mssql/connection_methods.rb +8 -1
  44. data/lib/arjdbc/mysql.rb +1 -1
  45. data/lib/arjdbc/mysql/adapter.rb +186 -150
  46. data/lib/arjdbc/mysql/connection_methods.rb +9 -9
  47. data/lib/arjdbc/mysql/explain_support.rb +85 -0
  48. data/lib/arjdbc/oracle.rb +1 -1
  49. data/lib/arjdbc/oracle/adapter.rb +232 -125
  50. data/lib/arjdbc/oracle/connection_methods.rb +2 -2
  51. data/lib/arjdbc/postgresql.rb +1 -1
  52. data/lib/arjdbc/postgresql/adapter.rb +134 -86
  53. data/lib/arjdbc/postgresql/connection_methods.rb +6 -4
  54. data/lib/arjdbc/postgresql/explain_support.rb +55 -0
  55. data/lib/arjdbc/sqlite3.rb +1 -1
  56. data/lib/arjdbc/sqlite3/adapter.rb +176 -108
  57. data/lib/arjdbc/sqlite3/connection_methods.rb +5 -5
  58. data/lib/arjdbc/sqlite3/explain_support.rb +32 -0
  59. data/lib/arjdbc/sybase/adapter.rb +7 -6
  60. data/lib/arjdbc/version.rb +1 -1
  61. data/pom.xml +1 -1
  62. data/rakelib/02-test.rake +9 -11
  63. data/rakelib/rails.rake +18 -10
  64. data/src/java/arjdbc/db2/DB2Module.java +70 -0
  65. data/src/java/arjdbc/derby/DerbyModule.java +24 -5
  66. data/src/java/arjdbc/hsqldb/HSQLDBModule.java +66 -0
  67. data/src/java/arjdbc/jdbc/AdapterJavaService.java +14 -7
  68. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +111 -89
  69. data/src/java/arjdbc/mysql/MySQLModule.java +79 -70
  70. data/src/java/arjdbc/oracle/OracleModule.java +74 -0
  71. data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +5 -10
  72. data/src/java/arjdbc/sqlite3/SQLite3Module.java +77 -0
  73. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +127 -0
  74. data/src/java/arjdbc/sqlite3/Sqlite3RubyJdbcConnection.java +25 -111
  75. data/src/java/arjdbc/util/QuotingUtils.java +104 -0
  76. data/test/abstract_db_create.rb +6 -6
  77. data/test/activerecord/connection_adapters/type_conversion_test.rb +2 -2
  78. data/test/assets/flowers.jpg +0 -0
  79. data/test/binary.rb +67 -0
  80. data/test/db/db2.rb +30 -7
  81. data/test/db/jdbc.rb +4 -2
  82. data/test/db/oracle.rb +18 -27
  83. data/test/db2_binary_test.rb +6 -0
  84. data/test/db2_serialize_test.rb +6 -0
  85. data/test/db2_simple_test.rb +20 -25
  86. data/test/db2_test.rb +71 -0
  87. data/test/derby_binary_test.rb +6 -0
  88. data/test/derby_migration_test.rb +42 -35
  89. data/test/derby_reset_column_information_test.rb +1 -0
  90. data/test/derby_row_locking_test.rb +17 -0
  91. data/test/derby_schema_dump_test.rb +9 -0
  92. data/test/derby_serialize_test.rb +6 -0
  93. data/test/derby_simple_test.rb +59 -17
  94. data/test/generic_jdbc_connection_test.rb +112 -5
  95. data/test/h2_binary_test.rb +6 -0
  96. data/test/h2_change_column_test.rb +1 -1
  97. data/test/h2_schema_dump_test.rb +25 -0
  98. data/test/h2_serialize_test.rb +6 -0
  99. data/test/h2_simple_test.rb +23 -9
  100. data/test/has_many_through.rb +18 -4
  101. data/test/hsqldb_binary_test.rb +6 -0
  102. data/test/hsqldb_schema_dump_test.rb +15 -0
  103. data/test/hsqldb_serialize_test.rb +6 -0
  104. data/test/hsqldb_simple_test.rb +1 -0
  105. data/test/informix_simple_test.rb +1 -1
  106. data/test/jdbc/db2.rb +23 -0
  107. data/test/jdbc/oracle.rb +23 -0
  108. data/test/jdbc_common.rb +3 -110
  109. data/test/jndi_callbacks_test.rb +0 -2
  110. data/test/jndi_test.rb +2 -0
  111. data/test/models/binary.rb +18 -0
  112. data/test/models/custom_pk_name.rb +1 -0
  113. data/test/models/data_types.rb +11 -2
  114. data/test/models/entry.rb +1 -1
  115. data/test/models/string_id.rb +2 -2
  116. data/test/models/thing.rb +1 -1
  117. data/test/models/topic.rb +32 -0
  118. data/test/mssql_legacy_types_test.rb +1 -1
  119. data/test/mssql_limit_offset_test.rb +13 -3
  120. data/test/mssql_serialize_test.rb +6 -0
  121. data/test/mysql_binary_test.rb +6 -0
  122. data/test/mysql_schema_dump_test.rb +220 -0
  123. data/test/mysql_serialize_test.rb +6 -0
  124. data/test/mysql_simple_test.rb +22 -2
  125. data/test/mysql_test.rb +93 -0
  126. data/test/oracle_binary_test.rb +6 -0
  127. data/test/oracle_limit_test.rb +2 -1
  128. data/test/oracle_serialize_test.rb +6 -0
  129. data/test/oracle_simple_test.rb +61 -0
  130. data/test/oracle_specific_test.rb +77 -26
  131. data/test/postgres_binary_test.rb +6 -0
  132. data/test/postgres_native_type_mapping_test.rb +12 -11
  133. data/test/postgres_nonseq_pkey_test.rb +1 -0
  134. data/test/postgres_reserved_test.rb +1 -0
  135. data/test/postgres_reset_column_information_test.rb +1 -0
  136. data/test/postgres_row_locking_test.rb +21 -0
  137. data/test/postgres_schema_dump_test.rb +88 -0
  138. data/test/postgres_schema_search_path_test.rb +1 -0
  139. data/test/postgres_simple_test.rb +62 -89
  140. data/test/postgres_table_alias_length_test.rb +1 -0
  141. data/test/postgres_test.rb +31 -0
  142. data/test/postgres_type_conversion_test.rb +16 -16
  143. data/test/row_locking.rb +69 -64
  144. data/test/schema_dump.rb +168 -0
  145. data/test/serialize.rb +277 -0
  146. data/test/simple.rb +326 -122
  147. data/test/sqlite3_serialize_test.rb +6 -0
  148. data/test/sqlite3_simple_test.rb +51 -84
  149. data/test/sqlite3_type_conversion_test.rb +101 -0
  150. data/test/test_helper.rb +224 -0
  151. metadata +325 -366
  152. data/README.rdoc +0 -214
  153. data/test/db/logger.rb +0 -3
  154. data/test/derby_multibyte_test.rb +0 -11
  155. data/test/mysql_info_test.rb +0 -123
@@ -1,3 +1,3 @@
1
1
  require 'arjdbc/jdbc'
2
- require 'arjdbc/sqlite3/connection_methods'
3
2
  require 'arjdbc/sqlite3/adapter'
3
+ require 'arjdbc/sqlite3/connection_methods'
@@ -1,49 +1,58 @@
1
1
  require 'arjdbc/jdbc/missing_functionality_helper'
2
-
3
- module ActiveRecord::ConnectionAdapters
4
- Sqlite3Adapter = Class.new(AbstractAdapter) unless const_defined?(:Sqlite3Adapter)
5
- end
2
+ require 'arjdbc/sqlite3/explain_support'
6
3
 
7
4
  module ::ArJdbc
8
5
  module SQLite3
6
+
9
7
  def self.column_selector
10
- [/sqlite/i, lambda {|cfg,col| col.extend(::ArJdbc::SQLite3::Column)}]
8
+ [ /sqlite/i, lambda { |cfg,col| col.extend(::ArJdbc::SQLite3::Column) } ]
11
9
  end
12
10
 
13
11
  def self.jdbc_connection_class
14
- ::ActiveRecord::ConnectionAdapters::Sqlite3JdbcConnection
12
+ ::ActiveRecord::ConnectionAdapters::SQLite3JdbcConnection
15
13
  end
16
-
14
+
17
15
  module Column
16
+
17
+ # #override {JdbcColumn#init_column}
18
18
  def init_column(name, default, *args)
19
- @default = nil if default =~ /NULL/
19
+ if default =~ /NULL/
20
+ @default = nil
21
+ else
22
+ super
23
+ end
20
24
  end
21
25
 
26
+ # #override {ActiveRecord::ConnectionAdapters::Column#type_cast}
22
27
  def type_cast(value)
23
28
  return nil if value.nil?
24
29
  case type
25
- when :string then value
26
- when :primary_key then defined?(value.to_i) ? value.to_i : (value ? 1 : 0)
30
+ when :string then value
31
+ when :primary_key
32
+ value.respond_to?(:to_i) ? value.to_i : ( value ? 1 : 0 )
27
33
  when :float then value.to_f
28
34
  when :decimal then self.class.value_to_decimal(value)
29
35
  when :boolean then self.class.value_to_boolean(value)
30
36
  else super
31
37
  end
32
38
  end
33
-
39
+
34
40
  private
41
+
35
42
  def simplified_type(field_type)
36
43
  case field_type
37
- when /boolean/i then :boolean
38
- when /text/i then :text
39
- when /varchar/i then :string
40
- when /int/i then :integer
41
- when /float/i then :float
42
- when /real|decimal/i then @scale == 0 ? :integer : :decimal
43
- when /datetime/i then :datetime
44
- when /date/i then :date
45
- when /time/i then :time
46
- when /blob/i then :binary
44
+ when /boolean/i then :boolean
45
+ when /text/i then :text
46
+ when /varchar/i then :string
47
+ when /int/i then :integer
48
+ when /float/i then :float
49
+ when /real|decimal/i then
50
+ extract_scale(field_type) == 0 ? :integer : :decimal
51
+ when /datetime/i then :datetime
52
+ when /date/i then :date
53
+ when /time/i then :time
54
+ when /blob/i then :binary
55
+ else super
47
56
  end
48
57
  end
49
58
 
@@ -74,132 +83,167 @@ module ::ArJdbc
74
83
 
75
84
  value
76
85
  end
77
- end
78
-
79
- def adapter_name #:nodoc:
80
- 'SQLite'
86
+
81
87
  end
82
88
 
83
89
  def self.arel2_visitors(config)
84
- {}.tap {|v| %w(sqlite3 jdbcsqlite3).each {|x| v[x] = ::Arel::Visitors::SQLite } }
90
+ {
91
+ 'sqlite3' => ::Arel::Visitors::SQLite,
92
+ 'jdbcsqlite3' => ::Arel::Visitors::SQLite
93
+ }
85
94
  end
86
-
87
- def supports_ddl_transactions?
95
+
96
+ ADAPTER_NAME = 'SQLite'
97
+
98
+ def adapter_name # :nodoc:
99
+ ADAPTER_NAME
100
+ end
101
+
102
+ NATIVE_DATABASE_TYPES = {
103
+ :primary_key => nil,
104
+ :string => { :name => "varchar", :limit => 255 },
105
+ :text => { :name => "text" },
106
+ :integer => { :name => "integer" },
107
+ :float => { :name => "float" },
108
+ :decimal => { :name => "decimal" },
109
+ :datetime => { :name => "datetime" },
110
+ :timestamp => { :name => "datetime" },
111
+ :time => { :name => "time" },
112
+ :date => { :name => "date" },
113
+ :binary => { :name => "blob" },
114
+ :boolean => { :name => "boolean" }
115
+ }
116
+
117
+ def native_database_types
118
+ types = super.merge(NATIVE_DATABASE_TYPES)
119
+ types[:primary_key] = default_primary_key_type
120
+ types
121
+ end
122
+
123
+ def modify_types(types)
124
+ super(types)
125
+ types.merge! NATIVE_DATABASE_TYPES
126
+ types
127
+ end
128
+
129
+ def default_primary_key_type
130
+ if supports_autoincrement?
131
+ 'integer PRIMARY KEY AUTOINCREMENT NOT NULL'
132
+ else
133
+ 'integer PRIMARY KEY NOT NULL'
134
+ end
135
+ end
136
+
137
+ def supports_ddl_transactions? # :nodoc:
88
138
  true # sqlite_version >= '2.0.0'
89
139
  end
90
-
91
- def supports_add_column?
140
+
141
+ def supports_savepoints? # :nodoc:
142
+ sqlite_version >= '3.6.8'
143
+ end
144
+
145
+ def supports_add_column? # :nodoc:
92
146
  sqlite_version >= '3.1.6'
93
147
  end
94
148
 
95
- def supports_count_distinct? #:nodoc:
149
+ def supports_count_distinct? # :nodoc:
96
150
  sqlite_version >= '3.2.6'
97
151
  end
98
152
 
99
- def supports_autoincrement? #:nodoc:
153
+ def supports_autoincrement? # :nodoc:
100
154
  sqlite_version >= '3.1.0'
101
155
  end
102
156
 
103
- def sqlite_version
104
- @sqlite_version ||= select_value('select sqlite_version(*)')
157
+ def supports_index_sort_order? # :nodoc:
158
+ sqlite_version >= '3.3.0'
105
159
  end
106
-
107
- def modify_types(tp)
108
- tp[:primary_key] = "integer primary key autoincrement not null"
109
- tp[:string] = { :name => "varchar", :limit => 255 }
110
- tp[:text] = { :name => "text" }
111
- tp[:float] = { :name => "float" }
112
- tp[:decimal] = { :name => "decimal" }
113
- tp[:datetime] = { :name => "datetime" }
114
- tp[:timestamp] = { :name => "datetime" }
115
- tp[:time] = { :name => "time" }
116
- tp[:date] = { :name => "date" }
117
- tp[:boolean] = { :name => "boolean" }
118
- tp[:binary] = { :name => "blob" }
119
- tp
160
+
161
+ def sqlite_version
162
+ @sqlite_version ||= select_value('SELECT sqlite_version(*)')
120
163
  end
121
-
164
+ private :sqlite_version
165
+
122
166
  def quote(value, column = nil)
123
- if value.kind_of?(String) && column && column.type == :binary && column.class.respond_to?(:string_to_binary)
124
- s = column.class.string_to_binary(value).unpack("H*")[0]
125
- "x'#{s}'"
167
+ if value.kind_of?(String)
168
+ column_type = column && column.type
169
+ if column_type == :binary && column.class.respond_to?(:string_to_binary)
170
+ "x'#{column.class.string_to_binary(value).unpack("H*")[0]}'"
171
+ else
172
+ super
173
+ end
126
174
  else
127
175
  super
128
176
  end
129
177
  end
130
178
 
131
- def quote_column_name(name) #:nodoc:
179
+ def quote_column_name(name) # :nodoc:
132
180
  %Q("#{name.to_s.gsub('"', '""')}") # "' kludge for emacs font-lock
133
181
  end
134
182
 
135
- def quote_string(str)
136
- str.gsub(/'/, "''")
137
- end
138
-
139
- def quoted_true
140
- %Q{'t'}
141
- end
142
-
143
- def quoted_false
144
- %Q{'f'}
145
- end
146
-
147
183
  # Quote date/time values for use in SQL input. Includes microseconds
148
184
  # if the value is a Time responding to usec.
149
- def quoted_date(value) #:nodoc:
185
+ def quoted_date(value) # :nodoc:
150
186
  if value.respond_to?(:usec)
151
187
  "#{super}.#{sprintf("%06d", value.usec)}"
152
188
  else
153
189
  super
154
190
  end
155
191
  end
156
-
157
- def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = []) #:nodoc:
158
- sql = substitute_binds(sql, binds)
159
- log(sql, name) { @connection.execute_update(sql) }
192
+
193
+ # NOTE: we have an extra binds argument at the end due 2.3 support.
194
+ def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = []) # :nodoc:
195
+ execute(sql, name, binds)
160
196
  id_value || last_insert_id
161
197
  end
198
+
199
+ def tables(name = nil, table_name = nil) # :nodoc:
200
+ sql = "SELECT name FROM sqlite_master WHERE type = 'table'"
201
+ if table_name
202
+ sql << " AND name = #{quote_table_name(table_name)}"
203
+ else
204
+ sql << " AND NOT name = 'sqlite_sequence'"
205
+ end
162
206
 
163
- def last_insert_id
164
- @connection.last_insert_row_id
207
+ select_rows(sql, name).map { |row| row[0] }
165
208
  end
166
209
 
167
- def tables(name = nil) #:nodoc:
168
- sql = <<-SQL
169
- SELECT name
170
- FROM sqlite_master
171
- WHERE type = 'table' AND NOT name = 'sqlite_sequence'
172
- SQL
173
-
174
- select_rows(sql, name).map do |row|
175
- row[0]
176
- end
210
+ def table_exists?(table_name)
211
+ table_name && tables(nil, table_name).any?
177
212
  end
178
-
213
+
214
+ IndexDefinition = ::ActiveRecord::ConnectionAdapters::IndexDefinition # :nodoc:
215
+
179
216
  def indexes(table_name, name = nil)
180
- result = select_rows("SELECT name, sql FROM sqlite_master WHERE tbl_name = #{quote_table_name(table_name)} AND type = 'index'", name)
181
-
182
- result.collect do |row|
183
- name = row[0]
184
- index_sql = row[1]
185
- unique = (index_sql =~ /unique/i)
186
- cols = index_sql.match(/\((.*)\)/)[1].gsub(/,/,' ').split.map do |c|
187
- match = /^"(.+)"$/.match(c); match ? match[1] : c
217
+ result = select_rows("SELECT name, sql FROM sqlite_master" <<
218
+ " WHERE tbl_name = #{quote_table_name(table_name)} AND type = 'index'", name)
219
+
220
+ result.map do |row|
221
+ name, index_sql = row[0], row[1]
222
+ unique = !! (index_sql =~ /unique/i)
223
+ columns = index_sql.match(/\((.*)\)/)[1].gsub(/,/,' ').split.map do |col|
224
+ match = /^"(.+)"$/.match(col); match ? match[1] : col
188
225
  end
189
- ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, name, unique, cols)
226
+ IndexDefinition.new(table_name, name, unique, columns)
190
227
  end
191
228
  end
192
229
 
193
- def recreate_database(name, options = {})
194
- tables.each{ |table| drop_table(table) }
230
+ def create_savepoint
231
+ execute("SAVEPOINT #{current_savepoint_name}")
195
232
  end
196
233
 
197
- def _execute(sql, name = nil)
198
- result = super
199
- ActiveRecord::ConnectionAdapters::JdbcConnection::insert?(sql) ? last_insert_id : result
234
+ def rollback_to_savepoint
235
+ execute("ROLLBACK TO SAVEPOINT #{current_savepoint_name}")
200
236
  end
201
237
 
202
- def select(sql, name=nil, binds = [])
238
+ def release_savepoint
239
+ execute("RELEASE SAVEPOINT #{current_savepoint_name}")
240
+ end
241
+
242
+ def recreate_database(name, options = {})
243
+ tables.each { |table| drop_table(table) }
244
+ end
245
+
246
+ def select(sql, name = nil, binds = [])
203
247
  execute(sql, name, binds).map do |row|
204
248
  record = {}
205
249
  row.each_key do |key|
@@ -222,7 +266,9 @@ module ::ArJdbc
222
266
 
223
267
  def jdbc_columns(table_name, name = nil) #:nodoc:
224
268
  table_structure(table_name).map do |field|
225
- ::ActiveRecord::ConnectionAdapters::SQLite3Column.new(@config, field['name'], field['dflt_value'], field['type'], field['notnull'] == 0)
269
+ ::ActiveRecord::ConnectionAdapters::SQLite3Column.new(
270
+ @config, field['name'], field['dflt_value'], field['type'], field['notnull'] == 0
271
+ )
226
272
  end
227
273
  end
228
274
 
@@ -258,7 +304,12 @@ module ::ArJdbc
258
304
  end
259
305
 
260
306
  def remove_column(table_name, *column_names) #:nodoc:
261
- raise ArgumentError.new("You must specify at least one column name. Example: remove_column(:people, :first_name)") if column_names.empty?
307
+ if column_names.empty?
308
+ raise ArgumentError.new(
309
+ "You must specify at least one column name." +
310
+ " Example: remove_column(:people, :first_name)"
311
+ )
312
+ end
262
313
  column_names.flatten.each do |column_name|
263
314
  alter_table(table_name) do |definition|
264
315
  definition.columns.delete(definition[column_name])
@@ -313,6 +364,7 @@ module ::ArJdbc
313
364
  end
314
365
 
315
366
  protected
367
+
316
368
  include ArJdbc::MissingFunctionalityHelper
317
369
 
318
370
  def translate_exception(exception, message)
@@ -323,6 +375,22 @@ module ::ArJdbc
323
375
  super
324
376
  end
325
377
  end
378
+
379
+ def last_insert_id
380
+ @connection.last_insert_row_id
381
+ end
382
+
383
+ def last_inserted_id(result)
384
+ last_insert_id
385
+ end
386
+
387
+ private
388
+
389
+ def _execute(sql, name = nil)
390
+ result = super
391
+ self.class.insert?(sql) ? last_insert_id : result
392
+ end
393
+
326
394
  end
327
395
  end
328
396
 
@@ -349,7 +417,7 @@ module ActiveRecord::ConnectionAdapters
349
417
  end
350
418
 
351
419
  def self.binary_to_string(value)
352
- if value.respond_to?(:force_encoding) && value.encoding != Encoding::ASCII_8BIT
420
+ if value.respond_to?(:encoding) && value.encoding != Encoding::ASCII_8BIT
353
421
  value = value.force_encoding(Encoding::ASCII_8BIT)
354
422
  end
355
423
  value
@@ -358,6 +426,7 @@ module ActiveRecord::ConnectionAdapters
358
426
 
359
427
  class SQLite3Adapter < JdbcAdapter
360
428
  include ArJdbc::SQLite3
429
+ include ArJdbc::SQLite3::ExplainSupport
361
430
 
362
431
  def jdbc_connection_class(spec)
363
432
  ::ArJdbc::SQLite3.jdbc_connection_class
@@ -368,21 +437,20 @@ module ActiveRecord::ConnectionAdapters
368
437
  end
369
438
 
370
439
  alias_chained_method :columns, :query_cache, :jdbc_columns
371
-
372
- protected
373
-
374
- def last_inserted_id(result)
375
- last_insert_id
376
- end
440
+
377
441
  end
378
442
 
379
443
  SQLiteAdapter = SQLite3Adapter
380
444
  end
381
445
 
446
+ # Don't need to load native sqlite3 adapter
447
+ $LOADED_FEATURES << 'active_record/connection_adapters/sqlite_adapter.rb'
448
+ $LOADED_FEATURES << 'active_record/connection_adapters/sqlite3_adapter.rb'
449
+
382
450
  # Fake out sqlite3/version driver for AR tests
383
451
  $LOADED_FEATURES << 'sqlite3/version.rb'
384
452
  module SQLite3
385
453
  module Version
386
454
  VERSION = '1.2.6' # query_cache_test.rb requires SQLite3::Version::VERSION > '1.2.5'
387
455
  end
388
- end
456
+ end
@@ -1,11 +1,11 @@
1
- # Don't need to load native sqlite3 adapter
2
- $LOADED_FEATURES << "active_record/connection_adapters/sqlite_adapter.rb"
3
- $LOADED_FEATURES << "active_record/connection_adapters/sqlite3_adapter.rb"
4
-
5
1
  class ActiveRecord::Base
6
2
  class << self
7
3
  def sqlite3_connection(config)
8
- require 'active_record/connection_adapters/jdbcsqlite3_adapter'
4
+ begin
5
+ require 'jdbc/sqlite3'
6
+ ::Jdbc::SQLite3.load_driver(:require) if defined?(::Jdbc::SQLite3.load_driver)
7
+ rescue LoadError # assuming driver.jar is on the class-path
8
+ end
9
9
 
10
10
  parse_sqlite3_config!(config)
11
11
  database = config[:database]
@@ -0,0 +1,32 @@
1
+ module ::ArJdbc
2
+ module SQLite3
3
+ module ExplainSupport
4
+ def supports_explain?
5
+ true
6
+ end
7
+
8
+ def explain(arel, binds = [])
9
+ sql = "EXPLAIN QUERY PLAN #{to_sql(arel, binds)}"
10
+ raw_result = execute(sql, "EXPLAIN", binds)
11
+ # TODO we should refactor to exce_query once it returns Result ASAP :
12
+ keys = raw_result[0] ? raw_result[0].keys : {}
13
+ rows = raw_result.map { |hash| hash.values }
14
+ ExplainPrettyPrinter.new.pp ActiveRecord::Result.new(keys, rows)
15
+ end
16
+
17
+ class ExplainPrettyPrinter # :nodoc:
18
+ # Pretty prints the result of a EXPLAIN QUERY PLAN in a way that resembles
19
+ # the output of the SQLite shell:
20
+ #
21
+ # 0|0|0|SEARCH TABLE users USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)
22
+ # 0|1|1|SCAN TABLE posts (~100000 rows)
23
+ #
24
+ def pp(result)
25
+ result.rows.map do |row|
26
+ row.join('|')
27
+ end.join("\n") + "\n"
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end