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.
- data/.gitignore +1 -0
- data/.travis.yml +5 -1
- data/Appraisals +5 -5
- data/Gemfile +9 -1
- data/Gemfile.lock +44 -10
- data/History.txt +126 -2
- data/README.md +246 -0
- data/Rakefile +34 -25
- data/activerecord-jdbc-adapter.gemspec +1 -1
- data/gemfiles/rails23.gemfile +5 -3
- data/gemfiles/rails23.gemfile.lock +26 -18
- data/gemfiles/rails30.gemfile +4 -2
- data/gemfiles/rails30.gemfile.lock +16 -8
- data/gemfiles/rails31.gemfile +4 -2
- data/gemfiles/rails31.gemfile.lock +16 -9
- data/gemfiles/rails32.gemfile +4 -2
- data/gemfiles/rails32.gemfile.lock +15 -8
- data/lib/active_record/connection_adapters/db2_adapter.rb +1 -0
- data/lib/arel/visitors/sql_server.rb +3 -0
- data/lib/arjdbc.rb +3 -5
- data/lib/arjdbc/db2.rb +1 -0
- data/lib/arjdbc/db2/adapter.rb +302 -196
- data/lib/arjdbc/db2/connection_methods.rb +18 -0
- data/lib/arjdbc/derby/active_record_patch.rb +12 -0
- data/lib/arjdbc/derby/adapter.rb +180 -158
- data/lib/arjdbc/derby/connection_methods.rb +5 -1
- data/lib/arjdbc/firebird/adapter.rb +27 -19
- data/lib/arjdbc/h2/adapter.rb +162 -7
- data/lib/arjdbc/h2/connection_methods.rb +5 -1
- data/lib/arjdbc/hsqldb.rb +1 -1
- data/lib/arjdbc/hsqldb/adapter.rb +96 -61
- data/lib/arjdbc/hsqldb/connection_methods.rb +5 -1
- data/lib/arjdbc/hsqldb/explain_support.rb +35 -0
- data/lib/arjdbc/informix/adapter.rb +56 -55
- data/lib/arjdbc/jdbc/adapter.rb +173 -86
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/column.rb +28 -23
- data/lib/arjdbc/jdbc/connection.rb +10 -6
- data/lib/arjdbc/jdbc/driver.rb +13 -5
- data/lib/arjdbc/jdbc/serialized_attributes_helper.rb +21 -0
- data/lib/arjdbc/mssql.rb +1 -1
- data/lib/arjdbc/mssql/adapter.rb +51 -53
- data/lib/arjdbc/mssql/connection_methods.rb +8 -1
- data/lib/arjdbc/mysql.rb +1 -1
- data/lib/arjdbc/mysql/adapter.rb +186 -150
- data/lib/arjdbc/mysql/connection_methods.rb +9 -9
- data/lib/arjdbc/mysql/explain_support.rb +85 -0
- data/lib/arjdbc/oracle.rb +1 -1
- data/lib/arjdbc/oracle/adapter.rb +232 -125
- data/lib/arjdbc/oracle/connection_methods.rb +2 -2
- data/lib/arjdbc/postgresql.rb +1 -1
- data/lib/arjdbc/postgresql/adapter.rb +134 -86
- data/lib/arjdbc/postgresql/connection_methods.rb +6 -4
- data/lib/arjdbc/postgresql/explain_support.rb +55 -0
- data/lib/arjdbc/sqlite3.rb +1 -1
- data/lib/arjdbc/sqlite3/adapter.rb +176 -108
- data/lib/arjdbc/sqlite3/connection_methods.rb +5 -5
- data/lib/arjdbc/sqlite3/explain_support.rb +32 -0
- data/lib/arjdbc/sybase/adapter.rb +7 -6
- data/lib/arjdbc/version.rb +1 -1
- data/pom.xml +1 -1
- data/rakelib/02-test.rake +9 -11
- data/rakelib/rails.rake +18 -10
- data/src/java/arjdbc/db2/DB2Module.java +70 -0
- data/src/java/arjdbc/derby/DerbyModule.java +24 -5
- data/src/java/arjdbc/hsqldb/HSQLDBModule.java +66 -0
- data/src/java/arjdbc/jdbc/AdapterJavaService.java +14 -7
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +111 -89
- data/src/java/arjdbc/mysql/MySQLModule.java +79 -70
- data/src/java/arjdbc/oracle/OracleModule.java +74 -0
- data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +5 -10
- data/src/java/arjdbc/sqlite3/SQLite3Module.java +77 -0
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +127 -0
- data/src/java/arjdbc/sqlite3/Sqlite3RubyJdbcConnection.java +25 -111
- data/src/java/arjdbc/util/QuotingUtils.java +104 -0
- data/test/abstract_db_create.rb +6 -6
- data/test/activerecord/connection_adapters/type_conversion_test.rb +2 -2
- data/test/assets/flowers.jpg +0 -0
- data/test/binary.rb +67 -0
- data/test/db/db2.rb +30 -7
- data/test/db/jdbc.rb +4 -2
- data/test/db/oracle.rb +18 -27
- data/test/db2_binary_test.rb +6 -0
- data/test/db2_serialize_test.rb +6 -0
- data/test/db2_simple_test.rb +20 -25
- data/test/db2_test.rb +71 -0
- data/test/derby_binary_test.rb +6 -0
- data/test/derby_migration_test.rb +42 -35
- data/test/derby_reset_column_information_test.rb +1 -0
- data/test/derby_row_locking_test.rb +17 -0
- data/test/derby_schema_dump_test.rb +9 -0
- data/test/derby_serialize_test.rb +6 -0
- data/test/derby_simple_test.rb +59 -17
- data/test/generic_jdbc_connection_test.rb +112 -5
- data/test/h2_binary_test.rb +6 -0
- data/test/h2_change_column_test.rb +1 -1
- data/test/h2_schema_dump_test.rb +25 -0
- data/test/h2_serialize_test.rb +6 -0
- data/test/h2_simple_test.rb +23 -9
- data/test/has_many_through.rb +18 -4
- data/test/hsqldb_binary_test.rb +6 -0
- data/test/hsqldb_schema_dump_test.rb +15 -0
- data/test/hsqldb_serialize_test.rb +6 -0
- data/test/hsqldb_simple_test.rb +1 -0
- data/test/informix_simple_test.rb +1 -1
- data/test/jdbc/db2.rb +23 -0
- data/test/jdbc/oracle.rb +23 -0
- data/test/jdbc_common.rb +3 -110
- data/test/jndi_callbacks_test.rb +0 -2
- data/test/jndi_test.rb +2 -0
- data/test/models/binary.rb +18 -0
- data/test/models/custom_pk_name.rb +1 -0
- data/test/models/data_types.rb +11 -2
- data/test/models/entry.rb +1 -1
- data/test/models/string_id.rb +2 -2
- data/test/models/thing.rb +1 -1
- data/test/models/topic.rb +32 -0
- data/test/mssql_legacy_types_test.rb +1 -1
- data/test/mssql_limit_offset_test.rb +13 -3
- data/test/mssql_serialize_test.rb +6 -0
- data/test/mysql_binary_test.rb +6 -0
- data/test/mysql_schema_dump_test.rb +220 -0
- data/test/mysql_serialize_test.rb +6 -0
- data/test/mysql_simple_test.rb +22 -2
- data/test/mysql_test.rb +93 -0
- data/test/oracle_binary_test.rb +6 -0
- data/test/oracle_limit_test.rb +2 -1
- data/test/oracle_serialize_test.rb +6 -0
- data/test/oracle_simple_test.rb +61 -0
- data/test/oracle_specific_test.rb +77 -26
- data/test/postgres_binary_test.rb +6 -0
- data/test/postgres_native_type_mapping_test.rb +12 -11
- data/test/postgres_nonseq_pkey_test.rb +1 -0
- data/test/postgres_reserved_test.rb +1 -0
- data/test/postgres_reset_column_information_test.rb +1 -0
- data/test/postgres_row_locking_test.rb +21 -0
- data/test/postgres_schema_dump_test.rb +88 -0
- data/test/postgres_schema_search_path_test.rb +1 -0
- data/test/postgres_simple_test.rb +62 -89
- data/test/postgres_table_alias_length_test.rb +1 -0
- data/test/postgres_test.rb +31 -0
- data/test/postgres_type_conversion_test.rb +16 -16
- data/test/row_locking.rb +69 -64
- data/test/schema_dump.rb +168 -0
- data/test/serialize.rb +277 -0
- data/test/simple.rb +326 -122
- data/test/sqlite3_serialize_test.rb +6 -0
- data/test/sqlite3_simple_test.rb +51 -84
- data/test/sqlite3_type_conversion_test.rb +101 -0
- data/test/test_helper.rb +224 -0
- metadata +325 -366
- data/README.rdoc +0 -214
- data/test/db/logger.rb +0 -3
- data/test/derby_multibyte_test.rb +0 -11
- data/test/mysql_info_test.rb +0 -123
data/lib/arjdbc/sqlite3.rb
CHANGED
@@ -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::
|
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
|
-
|
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
|
26
|
-
when :primary_key
|
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
|
38
|
-
when /text/i
|
39
|
-
when /varchar/i
|
40
|
-
when /int/i
|
41
|
-
when /float/i
|
42
|
-
when /real|decimal/i
|
43
|
-
|
44
|
-
when /
|
45
|
-
when /
|
46
|
-
when /
|
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
|
-
|
78
|
-
|
79
|
-
def adapter_name #:nodoc:
|
80
|
-
'SQLite'
|
86
|
+
|
81
87
|
end
|
82
88
|
|
83
89
|
def self.arel2_visitors(config)
|
84
|
-
{
|
90
|
+
{
|
91
|
+
'sqlite3' => ::Arel::Visitors::SQLite,
|
92
|
+
'jdbcsqlite3' => ::Arel::Visitors::SQLite
|
93
|
+
}
|
85
94
|
end
|
86
|
-
|
87
|
-
|
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
|
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?
|
149
|
+
def supports_count_distinct? # :nodoc:
|
96
150
|
sqlite_version >= '3.2.6'
|
97
151
|
end
|
98
152
|
|
99
|
-
def supports_autoincrement?
|
153
|
+
def supports_autoincrement? # :nodoc:
|
100
154
|
sqlite_version >= '3.1.0'
|
101
155
|
end
|
102
156
|
|
103
|
-
def
|
104
|
-
|
157
|
+
def supports_index_sort_order? # :nodoc:
|
158
|
+
sqlite_version >= '3.3.0'
|
105
159
|
end
|
106
|
-
|
107
|
-
def
|
108
|
-
|
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)
|
124
|
-
|
125
|
-
|
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)
|
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)
|
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
|
-
|
158
|
-
|
159
|
-
|
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
|
-
|
164
|
-
@connection.last_insert_row_id
|
207
|
+
select_rows(sql, name).map { |row| row[0] }
|
165
208
|
end
|
166
209
|
|
167
|
-
def
|
168
|
-
|
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
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
index_sql = row[1]
|
185
|
-
unique = (index_sql =~ /unique/i)
|
186
|
-
|
187
|
-
match = /^"(.+)"$/.match(
|
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
|
-
|
226
|
+
IndexDefinition.new(table_name, name, unique, columns)
|
190
227
|
end
|
191
228
|
end
|
192
229
|
|
193
|
-
def
|
194
|
-
|
230
|
+
def create_savepoint
|
231
|
+
execute("SAVEPOINT #{current_savepoint_name}")
|
195
232
|
end
|
196
233
|
|
197
|
-
def
|
198
|
-
|
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
|
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(
|
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
|
-
|
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?(:
|
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
|
-
|
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
|