activerecord 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- data/CHANGELOG +6023 -0
- data/README.rdoc +222 -0
- data/examples/associations.png +0 -0
- data/examples/performance.rb +162 -0
- data/examples/simple.rb +14 -0
- data/lib/active_record.rb +124 -0
- data/lib/active_record/aggregations.rb +277 -0
- data/lib/active_record/association_preload.rb +403 -0
- data/lib/active_record/associations.rb +2254 -0
- data/lib/active_record/associations/association_collection.rb +562 -0
- data/lib/active_record/associations/association_proxy.rb +295 -0
- data/lib/active_record/associations/belongs_to_association.rb +91 -0
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +78 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +137 -0
- data/lib/active_record/associations/has_many_association.rb +128 -0
- data/lib/active_record/associations/has_many_through_association.rb +116 -0
- data/lib/active_record/associations/has_one_association.rb +143 -0
- data/lib/active_record/associations/has_one_through_association.rb +40 -0
- data/lib/active_record/associations/through_association_scope.rb +154 -0
- data/lib/active_record/attribute_methods.rb +60 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +33 -0
- data/lib/active_record/attribute_methods/dirty.rb +95 -0
- data/lib/active_record/attribute_methods/primary_key.rb +50 -0
- data/lib/active_record/attribute_methods/query.rb +39 -0
- data/lib/active_record/attribute_methods/read.rb +116 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -0
- data/lib/active_record/attribute_methods/write.rb +37 -0
- data/lib/active_record/autosave_association.rb +369 -0
- data/lib/active_record/base.rb +1867 -0
- data/lib/active_record/callbacks.rb +288 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +365 -0
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +113 -0
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +57 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +329 -0
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +81 -0
- data/lib/active_record/connection_adapters/abstract/quoting.rb +72 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +739 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +543 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +212 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +643 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +1030 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +53 -0
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +401 -0
- data/lib/active_record/counter_cache.rb +115 -0
- data/lib/active_record/dynamic_finder_match.rb +53 -0
- data/lib/active_record/dynamic_scope_match.rb +32 -0
- data/lib/active_record/errors.rb +172 -0
- data/lib/active_record/fixtures.rb +1008 -0
- data/lib/active_record/locale/en.yml +40 -0
- data/lib/active_record/locking/optimistic.rb +172 -0
- data/lib/active_record/locking/pessimistic.rb +55 -0
- data/lib/active_record/log_subscriber.rb +48 -0
- data/lib/active_record/migration.rb +617 -0
- data/lib/active_record/named_scope.rb +138 -0
- data/lib/active_record/nested_attributes.rb +417 -0
- data/lib/active_record/observer.rb +140 -0
- data/lib/active_record/persistence.rb +291 -0
- data/lib/active_record/query_cache.rb +36 -0
- data/lib/active_record/railtie.rb +91 -0
- data/lib/active_record/railties/controller_runtime.rb +38 -0
- data/lib/active_record/railties/databases.rake +512 -0
- data/lib/active_record/reflection.rb +403 -0
- data/lib/active_record/relation.rb +393 -0
- data/lib/active_record/relation/batches.rb +89 -0
- data/lib/active_record/relation/calculations.rb +286 -0
- data/lib/active_record/relation/finder_methods.rb +355 -0
- data/lib/active_record/relation/predicate_builder.rb +41 -0
- data/lib/active_record/relation/query_methods.rb +261 -0
- data/lib/active_record/relation/spawn_methods.rb +112 -0
- data/lib/active_record/schema.rb +59 -0
- data/lib/active_record/schema_dumper.rb +195 -0
- data/lib/active_record/serialization.rb +60 -0
- data/lib/active_record/serializers/xml_serializer.rb +244 -0
- data/lib/active_record/session_store.rb +340 -0
- data/lib/active_record/test_case.rb +67 -0
- data/lib/active_record/timestamp.rb +88 -0
- data/lib/active_record/transactions.rb +356 -0
- data/lib/active_record/validations.rb +84 -0
- data/lib/active_record/validations/associated.rb +48 -0
- data/lib/active_record/validations/uniqueness.rb +185 -0
- data/lib/active_record/version.rb +9 -0
- data/lib/rails/generators/active_record.rb +27 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +25 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb +17 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +38 -0
- data/lib/rails/generators/active_record/model/templates/migration.rb +16 -0
- data/lib/rails/generators/active_record/model/templates/model.rb +5 -0
- data/lib/rails/generators/active_record/model/templates/module.rb +5 -0
- data/lib/rails/generators/active_record/observer/observer_generator.rb +15 -0
- data/lib/rails/generators/active_record/observer/templates/observer.rb +2 -0
- data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +24 -0
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +16 -0
- metadata +224 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'active_record/connection_adapters/sqlite_adapter'
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
class Base
|
5
|
+
# sqlite3 adapter reuses sqlite_connection.
|
6
|
+
def self.sqlite3_connection(config) # :nodoc:
|
7
|
+
# Require database.
|
8
|
+
unless config[:database]
|
9
|
+
raise ArgumentError, "No database file specified. Missing argument: database"
|
10
|
+
end
|
11
|
+
|
12
|
+
# Allow database path relative to Rails.root, but only if
|
13
|
+
# the database path is not the special path that tells
|
14
|
+
# Sqlite to build a database only in memory.
|
15
|
+
if defined?(Rails.root) && ':memory:' != config[:database]
|
16
|
+
config[:database] = File.expand_path(config[:database], Rails.root)
|
17
|
+
end
|
18
|
+
|
19
|
+
unless 'sqlite3' == config[:adapter]
|
20
|
+
raise ArgumentError, 'adapter name should be "sqlite3"'
|
21
|
+
end
|
22
|
+
|
23
|
+
unless self.class.const_defined?(:SQLite3)
|
24
|
+
require_library_or_gem(config[:adapter])
|
25
|
+
end
|
26
|
+
|
27
|
+
db = SQLite3::Database.new(
|
28
|
+
config[:database],
|
29
|
+
:results_as_hash => true
|
30
|
+
)
|
31
|
+
|
32
|
+
db.busy_timeout(config[:timeout]) unless config[:timeout].nil?
|
33
|
+
|
34
|
+
ConnectionAdapters::SQLite3Adapter.new(db, logger, config)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
module ConnectionAdapters #:nodoc:
|
39
|
+
class SQLite3Adapter < SQLiteAdapter # :nodoc:
|
40
|
+
|
41
|
+
# Returns the current database encoding format as a string, eg: 'UTF-8'
|
42
|
+
def encoding
|
43
|
+
if @connection.respond_to?(:encoding)
|
44
|
+
@connection.encoding.to_s
|
45
|
+
else
|
46
|
+
encoding = @connection.execute('PRAGMA encoding')
|
47
|
+
encoding[0]['encoding']
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,401 @@
|
|
1
|
+
require 'active_record/connection_adapters/abstract_adapter'
|
2
|
+
require 'active_support/core_ext/kernel/requires'
|
3
|
+
|
4
|
+
module ActiveRecord
|
5
|
+
module ConnectionAdapters #:nodoc:
|
6
|
+
class SQLiteColumn < Column #:nodoc:
|
7
|
+
class << self
|
8
|
+
def string_to_binary(value)
|
9
|
+
value.gsub(/\0|\%/n) do |b|
|
10
|
+
case b
|
11
|
+
when "\0" then "%00"
|
12
|
+
when "%" then "%25"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def binary_to_string(value)
|
18
|
+
if value.respond_to?(:force_encoding) && value.encoding != Encoding::ASCII_8BIT
|
19
|
+
value = value.force_encoding(Encoding::ASCII_8BIT)
|
20
|
+
end
|
21
|
+
|
22
|
+
value.gsub(/%00|%25/n) do |b|
|
23
|
+
case b
|
24
|
+
when "%00" then "\0"
|
25
|
+
when "%25" then "%"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# The SQLite adapter works with both the 2.x and 3.x series of SQLite with the sqlite-ruby
|
33
|
+
# drivers (available both as gems and from http://rubyforge.org/projects/sqlite-ruby/).
|
34
|
+
#
|
35
|
+
# Options:
|
36
|
+
#
|
37
|
+
# * <tt>:database</tt> - Path to the database file.
|
38
|
+
class SQLiteAdapter < AbstractAdapter
|
39
|
+
class Version
|
40
|
+
include Comparable
|
41
|
+
|
42
|
+
def initialize(version_string)
|
43
|
+
@version = version_string.split('.').map { |v| v.to_i }
|
44
|
+
end
|
45
|
+
|
46
|
+
def <=>(version_string)
|
47
|
+
@version <=> version_string.split('.').map { |v| v.to_i }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def initialize(connection, logger, config)
|
52
|
+
super(connection, logger)
|
53
|
+
@config = config
|
54
|
+
end
|
55
|
+
|
56
|
+
def adapter_name #:nodoc:
|
57
|
+
'SQLite'
|
58
|
+
end
|
59
|
+
|
60
|
+
def supports_ddl_transactions?
|
61
|
+
sqlite_version >= '2.0.0'
|
62
|
+
end
|
63
|
+
|
64
|
+
def supports_migrations? #:nodoc:
|
65
|
+
true
|
66
|
+
end
|
67
|
+
|
68
|
+
def supports_primary_key? #:nodoc:
|
69
|
+
true
|
70
|
+
end
|
71
|
+
|
72
|
+
def requires_reloading?
|
73
|
+
true
|
74
|
+
end
|
75
|
+
|
76
|
+
def supports_add_column?
|
77
|
+
sqlite_version >= '3.1.6'
|
78
|
+
end
|
79
|
+
|
80
|
+
def disconnect!
|
81
|
+
super
|
82
|
+
@connection.close rescue nil
|
83
|
+
end
|
84
|
+
|
85
|
+
def supports_count_distinct? #:nodoc:
|
86
|
+
sqlite_version >= '3.2.6'
|
87
|
+
end
|
88
|
+
|
89
|
+
def supports_autoincrement? #:nodoc:
|
90
|
+
sqlite_version >= '3.1.0'
|
91
|
+
end
|
92
|
+
|
93
|
+
def native_database_types #:nodoc:
|
94
|
+
{
|
95
|
+
:primary_key => default_primary_key_type,
|
96
|
+
:string => { :name => "varchar", :limit => 255 },
|
97
|
+
:text => { :name => "text" },
|
98
|
+
:integer => { :name => "integer" },
|
99
|
+
:float => { :name => "float" },
|
100
|
+
:decimal => { :name => "decimal" },
|
101
|
+
:datetime => { :name => "datetime" },
|
102
|
+
:timestamp => { :name => "datetime" },
|
103
|
+
:time => { :name => "time" },
|
104
|
+
:date => { :name => "date" },
|
105
|
+
:binary => { :name => "blob" },
|
106
|
+
:boolean => { :name => "boolean" }
|
107
|
+
}
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
# QUOTING ==================================================
|
112
|
+
|
113
|
+
def quote_string(s) #:nodoc:
|
114
|
+
@connection.class.quote(s)
|
115
|
+
end
|
116
|
+
|
117
|
+
def quote_column_name(name) #:nodoc:
|
118
|
+
%Q("#{name}")
|
119
|
+
end
|
120
|
+
|
121
|
+
# Quote date/time values for use in SQL input. Includes microseconds
|
122
|
+
# if the value is a Time responding to usec.
|
123
|
+
def quoted_date(value) #:nodoc:
|
124
|
+
if value.acts_like?(:time) && value.respond_to?(:usec)
|
125
|
+
"#{super}.#{sprintf("%06d", value.usec)}"
|
126
|
+
else
|
127
|
+
super
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
# DATABASE STATEMENTS ======================================
|
133
|
+
|
134
|
+
def execute(sql, name = nil) #:nodoc:
|
135
|
+
log(sql, name) { @connection.execute(sql) }
|
136
|
+
end
|
137
|
+
|
138
|
+
def update_sql(sql, name = nil) #:nodoc:
|
139
|
+
super
|
140
|
+
@connection.changes
|
141
|
+
end
|
142
|
+
|
143
|
+
def delete_sql(sql, name = nil) #:nodoc:
|
144
|
+
sql += " WHERE 1=1" unless sql =~ /WHERE/i
|
145
|
+
super sql, name
|
146
|
+
end
|
147
|
+
|
148
|
+
def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
|
149
|
+
super || @connection.last_insert_row_id
|
150
|
+
end
|
151
|
+
alias :create :insert_sql
|
152
|
+
|
153
|
+
def select_rows(sql, name = nil)
|
154
|
+
execute(sql, name).map do |row|
|
155
|
+
(0...(row.size / 2)).map { |i| row[i] }
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def begin_db_transaction #:nodoc:
|
160
|
+
@connection.transaction
|
161
|
+
end
|
162
|
+
|
163
|
+
def commit_db_transaction #:nodoc:
|
164
|
+
@connection.commit
|
165
|
+
end
|
166
|
+
|
167
|
+
def rollback_db_transaction #:nodoc:
|
168
|
+
@connection.rollback
|
169
|
+
end
|
170
|
+
|
171
|
+
# SCHEMA STATEMENTS ========================================
|
172
|
+
|
173
|
+
def tables(name = nil) #:nodoc:
|
174
|
+
sql = <<-SQL
|
175
|
+
SELECT name
|
176
|
+
FROM sqlite_master
|
177
|
+
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
|
178
|
+
SQL
|
179
|
+
|
180
|
+
execute(sql, name).map do |row|
|
181
|
+
row['name']
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def columns(table_name, name = nil) #:nodoc:
|
186
|
+
table_structure(table_name).map do |field|
|
187
|
+
SQLiteColumn.new(field['name'], field['dflt_value'], field['type'], field['notnull'].to_i == 0)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def indexes(table_name, name = nil) #:nodoc:
|
192
|
+
execute("PRAGMA index_list(#{quote_table_name(table_name)})", name).map do |row|
|
193
|
+
IndexDefinition.new(
|
194
|
+
table_name,
|
195
|
+
row['name'],
|
196
|
+
row['unique'].to_i != 0,
|
197
|
+
execute("PRAGMA index_info('#{row['name']}')").map { |col|
|
198
|
+
col['name']
|
199
|
+
})
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def primary_key(table_name) #:nodoc:
|
204
|
+
column = table_structure(table_name).find { |field|
|
205
|
+
field['pk'].to_i == 1
|
206
|
+
}
|
207
|
+
column && column['name']
|
208
|
+
end
|
209
|
+
|
210
|
+
def remove_index!(table_name, index_name) #:nodoc:
|
211
|
+
execute "DROP INDEX #{quote_column_name(index_name)}"
|
212
|
+
end
|
213
|
+
|
214
|
+
def rename_table(name, new_name)
|
215
|
+
execute "ALTER TABLE #{quote_table_name(name)} RENAME TO #{quote_table_name(new_name)}"
|
216
|
+
end
|
217
|
+
|
218
|
+
# See: http://www.sqlite.org/lang_altertable.html
|
219
|
+
# SQLite has an additional restriction on the ALTER TABLE statement
|
220
|
+
def valid_alter_table_options( type, options)
|
221
|
+
type.to_sym != :primary_key
|
222
|
+
end
|
223
|
+
|
224
|
+
def add_column(table_name, column_name, type, options = {}) #:nodoc:
|
225
|
+
if supports_add_column? && valid_alter_table_options( type, options )
|
226
|
+
super(table_name, column_name, type, options)
|
227
|
+
else
|
228
|
+
alter_table(table_name) do |definition|
|
229
|
+
definition.column(column_name, type, options)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def remove_column(table_name, *column_names) #:nodoc:
|
235
|
+
raise ArgumentError.new("You must specify at least one column name. Example: remove_column(:people, :first_name)") if column_names.empty?
|
236
|
+
column_names.flatten.each do |column_name|
|
237
|
+
alter_table(table_name) do |definition|
|
238
|
+
definition.columns.delete(definition[column_name])
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
alias :remove_columns :remove_column
|
243
|
+
|
244
|
+
def change_column_default(table_name, column_name, default) #:nodoc:
|
245
|
+
alter_table(table_name) do |definition|
|
246
|
+
definition[column_name].default = default
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
def change_column_null(table_name, column_name, null, default = nil)
|
251
|
+
unless null || default.nil?
|
252
|
+
execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
|
253
|
+
end
|
254
|
+
alter_table(table_name) do |definition|
|
255
|
+
definition[column_name].null = null
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
def change_column(table_name, column_name, type, options = {}) #:nodoc:
|
260
|
+
alter_table(table_name) do |definition|
|
261
|
+
include_default = options_include_default?(options)
|
262
|
+
definition[column_name].instance_eval do
|
263
|
+
self.type = type
|
264
|
+
self.limit = options[:limit] if options.include?(:limit)
|
265
|
+
self.default = options[:default] if include_default
|
266
|
+
self.null = options[:null] if options.include?(:null)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
def rename_column(table_name, column_name, new_column_name) #:nodoc:
|
272
|
+
unless columns(table_name).detect{|c| c.name == column_name.to_s }
|
273
|
+
raise ActiveRecord::ActiveRecordError, "Missing column #{table_name}.#{column_name}"
|
274
|
+
end
|
275
|
+
alter_table(table_name, :rename => {column_name.to_s => new_column_name.to_s})
|
276
|
+
end
|
277
|
+
|
278
|
+
def empty_insert_statement_value
|
279
|
+
"VALUES(NULL)"
|
280
|
+
end
|
281
|
+
|
282
|
+
protected
|
283
|
+
def select(sql, name = nil) #:nodoc:
|
284
|
+
execute(sql, name).map do |row|
|
285
|
+
record = {}
|
286
|
+
row.each do |key, value|
|
287
|
+
record[key.sub(/^"?\w+"?\./, '')] = value if key.is_a?(String)
|
288
|
+
end
|
289
|
+
record
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def table_structure(table_name)
|
294
|
+
structure = @connection.table_info(quote_table_name(table_name))
|
295
|
+
raise(ActiveRecord::StatementInvalid, "Could not find table '#{table_name}'") if structure.empty?
|
296
|
+
structure
|
297
|
+
end
|
298
|
+
|
299
|
+
def alter_table(table_name, options = {}) #:nodoc:
|
300
|
+
altered_table_name = "altered_#{table_name}"
|
301
|
+
caller = lambda {|definition| yield definition if block_given?}
|
302
|
+
|
303
|
+
transaction do
|
304
|
+
move_table(table_name, altered_table_name,
|
305
|
+
options.merge(:temporary => true))
|
306
|
+
move_table(altered_table_name, table_name, &caller)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
def move_table(from, to, options = {}, &block) #:nodoc:
|
311
|
+
copy_table(from, to, options, &block)
|
312
|
+
drop_table(from)
|
313
|
+
end
|
314
|
+
|
315
|
+
def copy_table(from, to, options = {}) #:nodoc:
|
316
|
+
options = options.merge(:id => (!columns(from).detect{|c| c.name == 'id'}.nil? && 'id' == primary_key(from).to_s))
|
317
|
+
create_table(to, options) do |definition|
|
318
|
+
@definition = definition
|
319
|
+
columns(from).each do |column|
|
320
|
+
column_name = options[:rename] ?
|
321
|
+
(options[:rename][column.name] ||
|
322
|
+
options[:rename][column.name.to_sym] ||
|
323
|
+
column.name) : column.name
|
324
|
+
|
325
|
+
@definition.column(column_name, column.type,
|
326
|
+
:limit => column.limit, :default => column.default,
|
327
|
+
:null => column.null)
|
328
|
+
end
|
329
|
+
@definition.primary_key(primary_key(from)) if primary_key(from)
|
330
|
+
yield @definition if block_given?
|
331
|
+
end
|
332
|
+
|
333
|
+
copy_table_indexes(from, to, options[:rename] || {})
|
334
|
+
copy_table_contents(from, to,
|
335
|
+
@definition.columns.map {|column| column.name},
|
336
|
+
options[:rename] || {})
|
337
|
+
end
|
338
|
+
|
339
|
+
def copy_table_indexes(from, to, rename = {}) #:nodoc:
|
340
|
+
indexes(from).each do |index|
|
341
|
+
name = index.name
|
342
|
+
if to == "altered_#{from}"
|
343
|
+
name = "temp_#{name}"
|
344
|
+
elsif from == "altered_#{to}"
|
345
|
+
name = name[5..-1]
|
346
|
+
end
|
347
|
+
|
348
|
+
to_column_names = columns(to).map { |c| c.name }
|
349
|
+
columns = index.columns.map {|c| rename[c] || c }.select do |column|
|
350
|
+
to_column_names.include?(column)
|
351
|
+
end
|
352
|
+
|
353
|
+
unless columns.empty?
|
354
|
+
# index name can't be the same
|
355
|
+
opts = { :name => name.gsub(/_(#{from})_/, "_#{to}_") }
|
356
|
+
opts[:unique] = true if index.unique
|
357
|
+
add_index(to, columns, opts)
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
def copy_table_contents(from, to, columns, rename = {}) #:nodoc:
|
363
|
+
column_mappings = Hash[*columns.map {|name| [name, name]}.flatten]
|
364
|
+
rename.inject(column_mappings) {|map, a| map[a.last] = a.first; map}
|
365
|
+
from_columns = columns(from).collect {|col| col.name}
|
366
|
+
columns = columns.find_all{|col| from_columns.include?(column_mappings[col])}
|
367
|
+
quoted_columns = columns.map { |col| quote_column_name(col) } * ','
|
368
|
+
|
369
|
+
quoted_to = quote_table_name(to)
|
370
|
+
@connection.execute "SELECT * FROM #{quote_table_name(from)}" do |row|
|
371
|
+
sql = "INSERT INTO #{quoted_to} (#{quoted_columns}) VALUES ("
|
372
|
+
sql << columns.map {|col| quote row[column_mappings[col]]} * ', '
|
373
|
+
sql << ')'
|
374
|
+
@connection.execute sql
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
def sqlite_version
|
379
|
+
@sqlite_version ||= SQLiteAdapter::Version.new(select_value('select sqlite_version(*)'))
|
380
|
+
end
|
381
|
+
|
382
|
+
def default_primary_key_type
|
383
|
+
if supports_autoincrement?
|
384
|
+
'INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL'
|
385
|
+
else
|
386
|
+
'INTEGER PRIMARY KEY NOT NULL'
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
def translate_exception(exception, message)
|
391
|
+
case exception.message
|
392
|
+
when /column(s)? .* (is|are) not unique/
|
393
|
+
RecordNotUnique.new(message, exception)
|
394
|
+
else
|
395
|
+
super
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
end
|
400
|
+
end
|
401
|
+
end
|