activerecord 3.1.3 → 3.1.4.rc1
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.md +27 -0
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -1
- data/lib/active_record/associations/builder/has_many.rb +7 -1
- data/lib/active_record/associations/collection_association.rb +7 -0
- data/lib/active_record/associations/collection_proxy.rb +8 -2
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +4 -0
- data/lib/active_record/associations/has_many_association.rb +2 -6
- data/lib/active_record/associations/has_many_through_association.rb +4 -0
- data/lib/active_record/attribute_methods/primary_key.rb +4 -1
- data/lib/active_record/base.rb +6 -6
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +10 -8
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
- data/lib/active_record/connection_adapters/abstract_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +19 -18
- data/lib/active_record/connection_adapters/mysql_adapter.rb +22 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +51 -11
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +12 -1
- data/lib/active_record/named_scope.rb +1 -1
- data/lib/active_record/relation.rb +2 -1
- data/lib/active_record/relation/finder_methods.rb +1 -1
- data/lib/active_record/version.rb +2 -2
- metadata +139 -131
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,30 @@
|
|
1
|
+
## Rails 3.1.4 (unreleased) ##
|
2
|
+
|
3
|
+
* Fix a custom primary key regression *GH 3987*
|
4
|
+
|
5
|
+
*Jon Leighton*
|
6
|
+
|
7
|
+
* Perf fix (second try): don't load records for `has many :dependent =>
|
8
|
+
:delete_all` *GH 3672*
|
9
|
+
|
10
|
+
*Jon Leighton*
|
11
|
+
|
12
|
+
* Fix accessing `proxy_association` method from an association extension
|
13
|
+
where the calls are chained. *GH #3890*
|
14
|
+
|
15
|
+
(E.g. `post.comments.where(bla).my_proxy_method`)
|
16
|
+
|
17
|
+
*Jon Leighton*
|
18
|
+
|
19
|
+
* Perf fix: MySQL primary key lookup was still slow for very large
|
20
|
+
tables. *GH 3678*
|
21
|
+
|
22
|
+
*Kenny J*
|
23
|
+
|
24
|
+
* Perf fix: If a table has no primary key, don't repeatedly ask the database for it.
|
25
|
+
|
26
|
+
*Julius de Bruijn*
|
27
|
+
|
1
28
|
## Rails 3.1.3 (unreleased) ##
|
2
29
|
|
3
30
|
* Perf fix: If we're deleting all records in an association, don't add a IN(..) clause
|
@@ -18,7 +18,7 @@ module ActiveRecord::Associations::Builder
|
|
18
18
|
model.send(:include, Module.new {
|
19
19
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
20
20
|
def destroy_associations
|
21
|
-
association(#{name.to_sym.inspect}).
|
21
|
+
association(#{name.to_sym.inspect}).delete_all_on_destroy
|
22
22
|
super
|
23
23
|
end
|
24
24
|
RUBY
|
@@ -44,12 +44,18 @@ module ActiveRecord::Associations::Builder
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def define_delete_all_dependency_method
|
47
|
+
name = self.name
|
48
|
+
model.send(:define_method, dependency_method_name) do
|
49
|
+
association(name).delete_all_on_destroy
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def define_nullify_dependency_method
|
47
54
|
name = self.name
|
48
55
|
model.send(:define_method, dependency_method_name) do
|
49
56
|
send(name).delete_all
|
50
57
|
end
|
51
58
|
end
|
52
|
-
alias :define_nullify_dependency_method :define_delete_all_dependency_method
|
53
59
|
|
54
60
|
def define_restrict_dependency_method
|
55
61
|
name = self.name
|
@@ -158,6 +158,13 @@ module ActiveRecord
|
|
158
158
|
end
|
159
159
|
end
|
160
160
|
|
161
|
+
# Called when the association is declared as :dependent => :delete_all. This is
|
162
|
+
# an optimised version which avoids loading the records into memory. Not really
|
163
|
+
# for public consumption.
|
164
|
+
def delete_all_on_destroy
|
165
|
+
scoped.delete_all
|
166
|
+
end
|
167
|
+
|
161
168
|
# Destroy all the records from this association.
|
162
169
|
#
|
163
170
|
# See destroy for more info.
|
@@ -48,8 +48,7 @@ module ActiveRecord
|
|
48
48
|
delegate :group, :order, :limit, :joins, :where, :preload, :eager_load, :includes, :from,
|
49
49
|
:lock, :readonly, :having, :to => :scoped
|
50
50
|
|
51
|
-
delegate :target, :load_target, :loaded?, :
|
52
|
-
:to => :@association
|
51
|
+
delegate :target, :load_target, :loaded?, :to => :@association
|
53
52
|
|
54
53
|
delegate :select, :find, :first, :last,
|
55
54
|
:build, :create, :create!,
|
@@ -69,6 +68,13 @@ module ActiveRecord
|
|
69
68
|
@association
|
70
69
|
end
|
71
70
|
|
71
|
+
def scoped
|
72
|
+
association = @association
|
73
|
+
association.scoped.extending do
|
74
|
+
define_method(:proxy_association) { association }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
72
78
|
def respond_to?(name, include_private = false)
|
73
79
|
super ||
|
74
80
|
(load_target && target.respond_to?(name, include_private)) ||
|
@@ -89,12 +89,8 @@ module ActiveRecord
|
|
89
89
|
records.each { |r| r.destroy }
|
90
90
|
update_counter(-records.length) unless inverse_updates_counter_cache?
|
91
91
|
else
|
92
|
-
|
93
|
-
|
94
|
-
unless records == load_target
|
95
|
-
keys = records.map { |r| r[reflection.association_primary_key] }
|
96
|
-
scope = scoped.where(reflection.association_primary_key => keys)
|
97
|
-
end
|
92
|
+
keys = records.map { |r| r[reflection.association_primary_key] }
|
93
|
+
scope = scoped.where(reflection.association_primary_key => keys)
|
98
94
|
|
99
95
|
if method == :delete_all
|
100
96
|
update_counter(-scope.delete_all)
|
@@ -13,7 +13,8 @@ module ActiveRecord
|
|
13
13
|
# Defines the primary key field -- can be overridden in subclasses. Overwriting will negate any effect of the
|
14
14
|
# primary_key_prefix_type setting, though.
|
15
15
|
def primary_key
|
16
|
-
@primary_key
|
16
|
+
@primary_key = reset_primary_key unless defined? @primary_key
|
17
|
+
@primary_key
|
17
18
|
end
|
18
19
|
|
19
20
|
# Returns a quoted version of the primary key name, used to construct SQL statements.
|
@@ -52,6 +53,8 @@ module ActiveRecord
|
|
52
53
|
def primary_key=(value)
|
53
54
|
@quoted_primary_key = nil
|
54
55
|
@primary_key = value
|
56
|
+
|
57
|
+
connection_pool.primary_keys[table_name] = @primary_key if connected?
|
55
58
|
end
|
56
59
|
|
57
60
|
# Sets the name of the primary key column to use to the given value,
|
data/lib/active_record/base.rb
CHANGED
@@ -2170,18 +2170,18 @@ MSG
|
|
2170
2170
|
include AutosaveAssociation, NestedAttributes
|
2171
2171
|
include Aggregations, Transactions, Reflection, Serialization
|
2172
2172
|
|
2173
|
-
NilClass.add_whiner(self) if NilClass.respond_to?(:add_whiner)
|
2174
|
-
|
2175
2173
|
# Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example,
|
2176
2174
|
# "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)).
|
2177
2175
|
# (Alias for the protected read_attribute method).
|
2178
|
-
|
2176
|
+
def [](attr_name)
|
2177
|
+
read_attribute(attr_name)
|
2178
|
+
end
|
2179
2179
|
|
2180
2180
|
# Updates the attribute identified by <tt>attr_name</tt> with the specified +value+.
|
2181
2181
|
# (Alias for the protected write_attribute method).
|
2182
|
-
|
2183
|
-
|
2184
|
-
|
2182
|
+
def []=(attr_name, value)
|
2183
|
+
write_attribute(attr_name, value)
|
2184
|
+
end
|
2185
2185
|
end
|
2186
2186
|
end
|
2187
2187
|
|
@@ -4,9 +4,11 @@ module ActiveRecord
|
|
4
4
|
module ConnectionAdapters # :nodoc:
|
5
5
|
module DatabaseStatements
|
6
6
|
# Converts an arel AST to SQL
|
7
|
-
def to_sql(arel)
|
7
|
+
def to_sql(arel, binds = [])
|
8
8
|
if arel.respond_to?(:ast)
|
9
|
-
visitor.accept(arel.ast)
|
9
|
+
visitor.accept(arel.ast) do
|
10
|
+
quote(*binds.shift.reverse)
|
11
|
+
end
|
10
12
|
else
|
11
13
|
arel
|
12
14
|
end
|
@@ -15,7 +17,7 @@ module ActiveRecord
|
|
15
17
|
# Returns an array of record hashes with the column names as keys and
|
16
18
|
# column values as values.
|
17
19
|
def select_all(arel, name = nil, binds = [])
|
18
|
-
select(to_sql(arel), name, binds)
|
20
|
+
select(to_sql(arel, binds), name, binds)
|
19
21
|
end
|
20
22
|
|
21
23
|
# Returns a record hash with the column names as keys and column values
|
@@ -35,7 +37,7 @@ module ActiveRecord
|
|
35
37
|
# Returns an array of the values of the first column in a select:
|
36
38
|
# select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
|
37
39
|
def select_values(arel, name = nil)
|
38
|
-
result = select_rows(to_sql(arel), name)
|
40
|
+
result = select_rows(to_sql(arel, []), name)
|
39
41
|
result.map { |v| v[0] }
|
40
42
|
end
|
41
43
|
|
@@ -86,19 +88,19 @@ module ActiveRecord
|
|
86
88
|
# If the next id was calculated in advance (as in Oracle), it should be
|
87
89
|
# passed in as +id_value+.
|
88
90
|
def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
|
89
|
-
sql, binds = sql_for_insert(to_sql(arel), pk, id_value, sequence_name, binds)
|
91
|
+
sql, binds = sql_for_insert(to_sql(arel, binds), pk, id_value, sequence_name, binds)
|
90
92
|
value = exec_insert(sql, name, binds)
|
91
93
|
id_value || last_inserted_id(value)
|
92
94
|
end
|
93
95
|
|
94
96
|
# Executes the update statement and returns the number of rows affected.
|
95
97
|
def update(arel, name = nil, binds = [])
|
96
|
-
exec_update(to_sql(arel), name, binds)
|
98
|
+
exec_update(to_sql(arel, binds), name, binds)
|
97
99
|
end
|
98
100
|
|
99
101
|
# Executes the delete statement and returns the number of rows affected.
|
100
102
|
def delete(arel, name = nil, binds = [])
|
101
|
-
exec_delete(to_sql(arel), name, binds)
|
103
|
+
exec_delete(to_sql(arel, binds), name, binds)
|
102
104
|
end
|
103
105
|
|
104
106
|
# Checks whether there is currently no transaction active. This is done
|
@@ -132,7 +134,7 @@ module ActiveRecord
|
|
132
134
|
#
|
133
135
|
# In order to get around this problem, #transaction will emulate the effect
|
134
136
|
# of nested transactions, by using savepoints:
|
135
|
-
# http://dev.mysql.com/doc/refman/5.0/en/
|
137
|
+
# http://dev.mysql.com/doc/refman/5.0/en/savepoint.html
|
136
138
|
# Savepoints are supported by MySQL and PostgreSQL, but not SQLite3.
|
137
139
|
#
|
138
140
|
# It is safe to call this method if a database transaction is already open,
|
@@ -128,7 +128,7 @@ module ActiveRecord
|
|
128
128
|
# Returns a bind substitution value given a +column+ and list of current
|
129
129
|
# +binds+
|
130
130
|
def substitute_at(column, index)
|
131
|
-
Arel.
|
131
|
+
Arel::Nodes::BindParam.new '?'
|
132
132
|
end
|
133
133
|
|
134
134
|
# REFERENTIAL INTEGRITY ====================================
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
require 'arel/visitors/bind_visitor'
|
2
3
|
|
3
|
-
gem 'mysql2', '~> 0.3.
|
4
|
+
gem 'mysql2', '~> 0.3.10'
|
4
5
|
require 'mysql2'
|
5
6
|
|
6
7
|
module ActiveRecord
|
@@ -129,8 +130,12 @@ module ActiveRecord
|
|
129
130
|
configure_connection
|
130
131
|
end
|
131
132
|
|
133
|
+
class BindSubstitution < Arel::Visitors::MySQL # :nodoc:
|
134
|
+
include Arel::Visitors::BindVisitor
|
135
|
+
end
|
136
|
+
|
132
137
|
def self.visitor_for(pool) # :nodoc:
|
133
|
-
|
138
|
+
BindSubstitution.new pool
|
134
139
|
end
|
135
140
|
|
136
141
|
def adapter_name
|
@@ -189,7 +194,7 @@ module ActiveRecord
|
|
189
194
|
end
|
190
195
|
|
191
196
|
def substitute_at(column, index)
|
192
|
-
Arel.
|
197
|
+
Arel::Nodes::BindParam.new "\0"
|
193
198
|
end
|
194
199
|
|
195
200
|
# REFERENTIAL INTEGRITY ====================================
|
@@ -297,17 +302,11 @@ module ActiveRecord
|
|
297
302
|
alias :create :insert_sql
|
298
303
|
|
299
304
|
def exec_insert(sql, name, binds)
|
300
|
-
|
301
|
-
|
302
|
-
# Pretend to support bind parameters
|
303
|
-
execute sql.gsub("\0") { quote(*binds.shift.reverse) }, name
|
305
|
+
execute to_sql(sql, binds), name
|
304
306
|
end
|
305
307
|
|
306
308
|
def exec_delete(sql, name, binds)
|
307
|
-
|
308
|
-
|
309
|
-
# Pretend to support bind parameters
|
310
|
-
execute sql.gsub("\0") { quote(*binds.shift.reverse) }, name
|
309
|
+
execute to_sql(sql, binds), name
|
311
310
|
@connection.affected_rows
|
312
311
|
end
|
313
312
|
alias :exec_update :exec_delete
|
@@ -572,12 +571,15 @@ module ActiveRecord
|
|
572
571
|
|
573
572
|
# Returns a table's primary key and belonging sequence.
|
574
573
|
def pk_and_sequence_for(table)
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
574
|
+
result = execute("SHOW CREATE TABLE #{quote_table_name(table)}", 'SCHEMA')
|
575
|
+
create_table = result.first[1]
|
576
|
+
|
577
|
+
if create_table.to_s =~ /PRIMARY KEY\s+\((.+)\)/
|
578
|
+
keys = $1.split(",").map { |key| key.gsub(/[`"]/, "") }
|
579
|
+
keys.length == 1 ? [keys.first, nil] : nil
|
580
|
+
else
|
581
|
+
nil
|
579
582
|
end
|
580
|
-
keys.length == 1 ? [keys.first, nil] : nil
|
581
583
|
end
|
582
584
|
|
583
585
|
# Returns just a table's primary key
|
@@ -675,8 +677,7 @@ module ActiveRecord
|
|
675
677
|
# Returns an array of record hashes with the column names as keys and
|
676
678
|
# column values as values.
|
677
679
|
def select(sql, name = nil, binds = [])
|
678
|
-
|
679
|
-
exec_query(sql.gsub("\0") { quote(*binds.shift.reverse) }, name).to_a
|
680
|
+
exec_query(sql, name).to_a
|
680
681
|
end
|
681
682
|
|
682
683
|
def exec_query(sql, name = 'SQL', binds = [])
|
@@ -3,6 +3,7 @@ require 'active_support/core_ext/kernel/requires'
|
|
3
3
|
require 'active_support/core_ext/object/blank'
|
4
4
|
require 'set'
|
5
5
|
require 'active_record/connection_adapters/statement_pool'
|
6
|
+
require 'arel/visitors/bind_visitor'
|
6
7
|
|
7
8
|
gem 'mysql', '~> 2.8.1'
|
8
9
|
require 'mysql'
|
@@ -228,8 +229,18 @@ module ActiveRecord
|
|
228
229
|
connect
|
229
230
|
end
|
230
231
|
|
232
|
+
class BindSubstitution < Arel::Visitors::MySQL # :nodoc:
|
233
|
+
include Arel::Visitors::BindVisitor
|
234
|
+
end
|
235
|
+
|
231
236
|
def self.visitor_for(pool) # :nodoc:
|
232
|
-
|
237
|
+
config = pool.spec.config
|
238
|
+
|
239
|
+
if config.fetch(:prepared_statements) { true }
|
240
|
+
Arel::Visitors::MySQL.new pool
|
241
|
+
else
|
242
|
+
BindSubstitution.new pool
|
243
|
+
end
|
233
244
|
end
|
234
245
|
|
235
246
|
def adapter_name #:nodoc:
|
@@ -688,7 +699,7 @@ module ActiveRecord
|
|
688
699
|
table, arguments = args.shift, args
|
689
700
|
method = :"#{command}_sql"
|
690
701
|
|
691
|
-
if respond_to?(method)
|
702
|
+
if respond_to?(method, true)
|
692
703
|
send(method, table, *arguments)
|
693
704
|
else
|
694
705
|
raise "Unknown method called : #{method}(#{arguments.inspect})"
|
@@ -755,13 +766,16 @@ module ActiveRecord
|
|
755
766
|
|
756
767
|
# Returns a table's primary key and belonging sequence.
|
757
768
|
def pk_and_sequence_for(table) #:nodoc:
|
758
|
-
|
759
|
-
|
760
|
-
result.each_hash do |h|
|
761
|
-
keys << h["Column_name"]
|
762
|
-
end
|
769
|
+
result = execute("SHOW CREATE TABLE #{quote_table_name(table)}", 'SCHEMA')
|
770
|
+
create_table = result.fetch_hash["Create Table"]
|
763
771
|
result.free
|
764
|
-
|
772
|
+
|
773
|
+
if create_table.to_s =~ /PRIMARY KEY\s+\((.+)\)/
|
774
|
+
keys = $1.split(",").map { |key| key.gsub(/[`"]/, "") }
|
775
|
+
keys.length == 1 ? [keys.first, nil] : nil
|
776
|
+
else
|
777
|
+
nil
|
778
|
+
end
|
765
779
|
end
|
766
780
|
|
767
781
|
# Returns just a table's primary key
|
@@ -2,6 +2,7 @@ require 'active_record/connection_adapters/abstract_adapter'
|
|
2
2
|
require 'active_support/core_ext/kernel/requires'
|
3
3
|
require 'active_support/core_ext/object/blank'
|
4
4
|
require 'active_record/connection_adapters/statement_pool'
|
5
|
+
require 'arel/visitors/bind_visitor'
|
5
6
|
|
6
7
|
# Make sure we're using pg high enough for PGResult#values
|
7
8
|
gem 'pg', '~> 0.11'
|
@@ -300,9 +301,16 @@ module ActiveRecord
|
|
300
301
|
end
|
301
302
|
end
|
302
303
|
|
304
|
+
class BindSubstitution < Arel::Visitors::PostgreSQL # :nodoc:
|
305
|
+
include Arel::Visitors::BindVisitor
|
306
|
+
end
|
307
|
+
|
303
308
|
# Initializes and connects a PostgreSQL adapter.
|
304
309
|
def initialize(connection, logger, connection_parameters, config)
|
305
310
|
super(connection, logger)
|
311
|
+
|
312
|
+
connection_parameters.delete :prepared_statements
|
313
|
+
|
306
314
|
@connection_parameters, @config = connection_parameters, config
|
307
315
|
|
308
316
|
# @local_tz is initialized as nil to avoid warnings when connect tries to use it
|
@@ -321,7 +329,12 @@ module ActiveRecord
|
|
321
329
|
end
|
322
330
|
|
323
331
|
def self.visitor_for(pool) # :nodoc:
|
324
|
-
|
332
|
+
config = pool.spec.config
|
333
|
+
if config.fetch(:prepared_statements) { true }
|
334
|
+
Arel::Visitors::PostgreSQL.new pool
|
335
|
+
else
|
336
|
+
BindSubstitution.new pool
|
337
|
+
end
|
325
338
|
end
|
326
339
|
|
327
340
|
# Clears the prepared statements cache.
|
@@ -594,7 +607,7 @@ module ActiveRecord
|
|
594
607
|
end
|
595
608
|
|
596
609
|
def substitute_at(column, index)
|
597
|
-
Arel.
|
610
|
+
Arel::Nodes::BindParam.new "$#{index + 1}"
|
598
611
|
end
|
599
612
|
|
600
613
|
def exec_query(sql, name = 'SQL', binds = [])
|
@@ -873,18 +886,45 @@ module ActiveRecord
|
|
873
886
|
def pk_and_sequence_for(table) #:nodoc:
|
874
887
|
# First try looking for a sequence with a dependency on the
|
875
888
|
# given table's primary key.
|
876
|
-
result =
|
889
|
+
result = query(<<-end_sql, 'PK and serial sequence')[0]
|
877
890
|
SELECT attr.attname, seq.relname
|
878
|
-
FROM pg_class
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
AND
|
891
|
+
FROM pg_class seq,
|
892
|
+
pg_attribute attr,
|
893
|
+
pg_depend dep,
|
894
|
+
pg_namespace name,
|
895
|
+
pg_constraint cons
|
896
|
+
WHERE seq.oid = dep.objid
|
897
|
+
AND seq.relkind = 'S'
|
898
|
+
AND attr.attrelid = dep.refobjid
|
899
|
+
AND attr.attnum = dep.refobjsubid
|
900
|
+
AND attr.attrelid = cons.conrelid
|
901
|
+
AND attr.attnum = cons.conkey[1]
|
902
|
+
AND cons.contype = 'p'
|
903
|
+
AND dep.refobjid = '#{quote_table_name(table)}'::regclass
|
885
904
|
end_sql
|
886
905
|
|
887
|
-
|
906
|
+
if result.nil? or result.empty?
|
907
|
+
# If that fails, try parsing the primary key's default value.
|
908
|
+
# Support the 7.x and 8.0 nextval('foo'::text) as well as
|
909
|
+
# the 8.1+ nextval('foo'::regclass).
|
910
|
+
result = query(<<-end_sql, 'PK and custom sequence')[0]
|
911
|
+
SELECT attr.attname,
|
912
|
+
CASE
|
913
|
+
WHEN split_part(def.adsrc, '''', 2) ~ '.' THEN
|
914
|
+
substr(split_part(def.adsrc, '''', 2),
|
915
|
+
strpos(split_part(def.adsrc, '''', 2), '.')+1)
|
916
|
+
ELSE split_part(def.adsrc, '''', 2)
|
917
|
+
END
|
918
|
+
FROM pg_class t
|
919
|
+
JOIN pg_attribute attr ON (t.oid = attrelid)
|
920
|
+
JOIN pg_attrdef def ON (adrelid = attrelid AND adnum = attnum)
|
921
|
+
JOIN pg_constraint cons ON (conrelid = adrelid AND adnum = conkey[1])
|
922
|
+
WHERE t.oid = '#{quote_table_name(table)}'::regclass
|
923
|
+
AND cons.contype = 'p'
|
924
|
+
AND def.adsrc ~* 'nextval'
|
925
|
+
end_sql
|
926
|
+
end
|
927
|
+
|
888
928
|
[result.first, result.last]
|
889
929
|
rescue
|
890
930
|
nil
|
@@ -2,6 +2,7 @@ require 'active_record/connection_adapters/abstract_adapter'
|
|
2
2
|
require 'active_support/core_ext/kernel/requires'
|
3
3
|
require 'active_record/connection_adapters/statement_pool'
|
4
4
|
require 'active_support/core_ext/string/encoding'
|
5
|
+
require 'arel/visitors/bind_visitor'
|
5
6
|
|
6
7
|
module ActiveRecord
|
7
8
|
module ConnectionAdapters #:nodoc:
|
@@ -85,6 +86,10 @@ module ActiveRecord
|
|
85
86
|
end
|
86
87
|
end
|
87
88
|
|
89
|
+
class BindSubstitution < Arel::Visitors::SQLite # :nodoc:
|
90
|
+
include Arel::Visitors::BindVisitor
|
91
|
+
end
|
92
|
+
|
88
93
|
def initialize(connection, logger, config)
|
89
94
|
super(connection, logger)
|
90
95
|
@statements = StatementPool.new(@connection,
|
@@ -93,7 +98,13 @@ module ActiveRecord
|
|
93
98
|
end
|
94
99
|
|
95
100
|
def self.visitor_for(pool) # :nodoc:
|
96
|
-
|
101
|
+
config = pool.spec.config
|
102
|
+
|
103
|
+
if config.fetch(:prepared_statements) { true }
|
104
|
+
Arel::Visitors::SQLite.new pool
|
105
|
+
else
|
106
|
+
BindSubstitution.new pool
|
107
|
+
end
|
97
108
|
end
|
98
109
|
|
99
110
|
def adapter_name #:nodoc:
|
@@ -176,7 +176,7 @@ module ActiveRecord
|
|
176
176
|
extension = Module.new(&Proc.new) if block_given?
|
177
177
|
|
178
178
|
scope_proc = lambda do |*args|
|
179
|
-
options = scope_options.respond_to?(:call) ? scope_options.call(*args) : scope_options
|
179
|
+
options = scope_options.respond_to?(:call) ? unscoped { scope_options.call(*args) } : scope_options
|
180
180
|
options = scoped.apply_finder_options(options) if options.is_a?(Hash)
|
181
181
|
|
182
182
|
relation = scoped.merge(options)
|
@@ -81,6 +81,7 @@ module ActiveRecord
|
|
81
81
|
end
|
82
82
|
|
83
83
|
def initialize_copy(other)
|
84
|
+
@bind_values = @bind_values.dup
|
84
85
|
reset
|
85
86
|
end
|
86
87
|
|
@@ -394,7 +395,7 @@ module ActiveRecord
|
|
394
395
|
end
|
395
396
|
|
396
397
|
def to_sql
|
397
|
-
@to_sql ||= klass.connection.to_sql(arel)
|
398
|
+
@to_sql ||= klass.connection.to_sql(arel, @bind_values.dup)
|
398
399
|
end
|
399
400
|
|
400
401
|
def where_values_hash
|
@@ -208,7 +208,7 @@ module ActiveRecord
|
|
208
208
|
def find_with_associations
|
209
209
|
join_dependency = construct_join_dependency_for_association_find
|
210
210
|
relation = construct_relation_for_association_find(join_dependency)
|
211
|
-
rows = connection.select_all(relation, 'SQL', relation.bind_values)
|
211
|
+
rows = connection.select_all(relation, 'SQL', relation.bind_values.dup)
|
212
212
|
join_dependency.instantiate(rows)
|
213
213
|
rescue ThrowResult
|
214
214
|
[]
|
metadata
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 15424071
|
5
|
+
prerelease: 6
|
6
6
|
segments:
|
7
7
|
- 3
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
|
9
|
+
- 4
|
10
|
+
- rc
|
11
|
+
- 1
|
12
|
+
version: 3.1.4.rc1
|
11
13
|
platform: ruby
|
12
14
|
authors:
|
13
15
|
- David Heinemeier Hansson
|
@@ -15,61 +17,64 @@ autorequire:
|
|
15
17
|
bindir: bin
|
16
18
|
cert_chain: []
|
17
19
|
|
18
|
-
date:
|
20
|
+
date: 2012-02-22 00:00:00 Z
|
19
21
|
dependencies:
|
20
22
|
- !ruby/object:Gem::Dependency
|
21
23
|
name: activesupport
|
22
|
-
type: :runtime
|
23
24
|
prerelease: false
|
24
|
-
|
25
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
26
|
none: false
|
26
27
|
requirements:
|
27
28
|
- - "="
|
28
29
|
- !ruby/object:Gem::Version
|
29
|
-
hash:
|
30
|
+
hash: 15424071
|
30
31
|
segments:
|
31
32
|
- 3
|
32
33
|
- 1
|
33
|
-
-
|
34
|
-
|
35
|
-
|
34
|
+
- 4
|
35
|
+
- rc
|
36
|
+
- 1
|
37
|
+
version: 3.1.4.rc1
|
38
|
+
type: :runtime
|
39
|
+
version_requirements: *id001
|
36
40
|
- !ruby/object:Gem::Dependency
|
37
41
|
name: activemodel
|
38
|
-
type: :runtime
|
39
42
|
prerelease: false
|
40
|
-
|
43
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
44
|
none: false
|
42
45
|
requirements:
|
43
46
|
- - "="
|
44
47
|
- !ruby/object:Gem::Version
|
45
|
-
hash:
|
48
|
+
hash: 15424071
|
46
49
|
segments:
|
47
50
|
- 3
|
48
51
|
- 1
|
49
|
-
-
|
50
|
-
|
51
|
-
|
52
|
+
- 4
|
53
|
+
- rc
|
54
|
+
- 1
|
55
|
+
version: 3.1.4.rc1
|
56
|
+
type: :runtime
|
57
|
+
version_requirements: *id002
|
52
58
|
- !ruby/object:Gem::Dependency
|
53
59
|
name: arel
|
54
|
-
type: :runtime
|
55
60
|
prerelease: false
|
56
|
-
|
61
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
62
|
none: false
|
58
63
|
requirements:
|
59
64
|
- - ~>
|
60
65
|
- !ruby/object:Gem::Version
|
61
|
-
hash:
|
66
|
+
hash: 1
|
62
67
|
segments:
|
63
68
|
- 2
|
64
69
|
- 2
|
65
|
-
-
|
66
|
-
version: 2.2.
|
67
|
-
|
70
|
+
- 3
|
71
|
+
version: 2.2.3
|
72
|
+
type: :runtime
|
73
|
+
version_requirements: *id003
|
68
74
|
- !ruby/object:Gem::Dependency
|
69
75
|
name: tzinfo
|
70
|
-
type: :runtime
|
71
76
|
prerelease: false
|
72
|
-
|
77
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
73
78
|
none: false
|
74
79
|
requirements:
|
75
80
|
- - ~>
|
@@ -80,7 +85,8 @@ dependencies:
|
|
80
85
|
- 3
|
81
86
|
- 29
|
82
87
|
version: 0.3.29
|
83
|
-
|
88
|
+
type: :runtime
|
89
|
+
version_requirements: *id004
|
84
90
|
description: Databases on Rails. Build a persistent domain model by mapping database tables to Ruby classes. Strong conventions for associations, validations, aggregations, migrations, and testing come baked-in.
|
85
91
|
email: david@loudthinking.com
|
86
92
|
executables: []
|
@@ -93,132 +99,132 @@ files:
|
|
93
99
|
- CHANGELOG.md
|
94
100
|
- MIT-LICENSE
|
95
101
|
- README.rdoc
|
102
|
+
- examples/associations.png
|
96
103
|
- examples/performance.rb
|
97
104
|
- examples/simple.rb
|
98
|
-
-
|
99
|
-
- lib/active_record/
|
105
|
+
- lib/active_record/aggregations.rb
|
106
|
+
- lib/active_record/associations/alias_tracker.rb
|
107
|
+
- lib/active_record/associations/association.rb
|
108
|
+
- lib/active_record/associations/association_scope.rb
|
109
|
+
- lib/active_record/associations/belongs_to_association.rb
|
110
|
+
- lib/active_record/associations/belongs_to_polymorphic_association.rb
|
111
|
+
- lib/active_record/associations/builder/association.rb
|
112
|
+
- lib/active_record/associations/builder/belongs_to.rb
|
113
|
+
- lib/active_record/associations/builder/collection_association.rb
|
114
|
+
- lib/active_record/associations/builder/has_and_belongs_to_many.rb
|
115
|
+
- lib/active_record/associations/builder/has_many.rb
|
116
|
+
- lib/active_record/associations/builder/has_one.rb
|
117
|
+
- lib/active_record/associations/builder/singular_association.rb
|
118
|
+
- lib/active_record/associations/collection_association.rb
|
119
|
+
- lib/active_record/associations/collection_proxy.rb
|
120
|
+
- lib/active_record/associations/has_and_belongs_to_many_association.rb
|
121
|
+
- lib/active_record/associations/has_many_association.rb
|
122
|
+
- lib/active_record/associations/has_many_through_association.rb
|
123
|
+
- lib/active_record/associations/has_one_association.rb
|
124
|
+
- lib/active_record/associations/has_one_through_association.rb
|
125
|
+
- lib/active_record/associations/join_dependency/join_association.rb
|
126
|
+
- lib/active_record/associations/join_dependency/join_base.rb
|
127
|
+
- lib/active_record/associations/join_dependency/join_part.rb
|
128
|
+
- lib/active_record/associations/join_dependency.rb
|
129
|
+
- lib/active_record/associations/join_helper.rb
|
130
|
+
- lib/active_record/associations/preloader/association.rb
|
131
|
+
- lib/active_record/associations/preloader/belongs_to.rb
|
132
|
+
- lib/active_record/associations/preloader/collection_association.rb
|
133
|
+
- lib/active_record/associations/preloader/has_and_belongs_to_many.rb
|
134
|
+
- lib/active_record/associations/preloader/has_many.rb
|
135
|
+
- lib/active_record/associations/preloader/has_many_through.rb
|
136
|
+
- lib/active_record/associations/preloader/has_one.rb
|
137
|
+
- lib/active_record/associations/preloader/has_one_through.rb
|
138
|
+
- lib/active_record/associations/preloader/singular_association.rb
|
139
|
+
- lib/active_record/associations/preloader/through_association.rb
|
140
|
+
- lib/active_record/associations/preloader.rb
|
141
|
+
- lib/active_record/associations/singular_association.rb
|
142
|
+
- lib/active_record/associations/through_association.rb
|
100
143
|
- lib/active_record/associations.rb
|
101
|
-
- lib/active_record/
|
102
|
-
- lib/active_record/relation.rb
|
103
|
-
- lib/active_record/migration.rb
|
104
|
-
- lib/active_record/railties/jdbcmysql_error.rb
|
105
|
-
- lib/active_record/railties/console_sandbox.rb
|
106
|
-
- lib/active_record/railties/databases.rake
|
107
|
-
- lib/active_record/railties/controller_runtime.rb
|
108
|
-
- lib/active_record/nested_attributes.rb
|
109
|
-
- lib/active_record/dynamic_finder_match.rb
|
110
|
-
- lib/active_record/attribute_methods.rb
|
111
|
-
- lib/active_record/relation/spawn_methods.rb
|
112
|
-
- lib/active_record/relation/predicate_builder.rb
|
113
|
-
- lib/active_record/relation/batches.rb
|
114
|
-
- lib/active_record/relation/calculations.rb
|
115
|
-
- lib/active_record/relation/finder_methods.rb
|
116
|
-
- lib/active_record/relation/query_methods.rb
|
117
|
-
- lib/active_record/schema.rb
|
118
|
-
- lib/active_record/named_scope.rb
|
119
|
-
- lib/active_record/schema_dumper.rb
|
120
|
-
- lib/active_record/migration/command_recorder.rb
|
121
|
-
- lib/active_record/errors.rb
|
122
|
-
- lib/active_record/test_case.rb
|
123
|
-
- lib/active_record/fixtures.rb
|
144
|
+
- lib/active_record/attribute_methods/before_type_cast.rb
|
124
145
|
- lib/active_record/attribute_methods/dirty.rb
|
125
146
|
- lib/active_record/attribute_methods/primary_key.rb
|
126
|
-
- lib/active_record/attribute_methods/time_zone_conversion.rb
|
127
147
|
- lib/active_record/attribute_methods/query.rb
|
128
|
-
- lib/active_record/attribute_methods/write.rb
|
129
148
|
- lib/active_record/attribute_methods/read.rb
|
130
|
-
- lib/active_record/attribute_methods/
|
131
|
-
- lib/active_record/
|
132
|
-
- lib/active_record/
|
133
|
-
- lib/active_record/locking/optimistic.rb
|
134
|
-
- lib/active_record/observer.rb
|
135
|
-
- lib/active_record/log_subscriber.rb
|
136
|
-
- lib/active_record/reflection.rb
|
137
|
-
- lib/active_record/counter_cache.rb
|
138
|
-
- lib/active_record/version.rb
|
139
|
-
- lib/active_record/transactions.rb
|
140
|
-
- lib/active_record/serialization.rb
|
141
|
-
- lib/active_record/timestamp.rb
|
142
|
-
- lib/active_record/railtie.rb
|
143
|
-
- lib/active_record/session_store.rb
|
144
|
-
- lib/active_record/persistence.rb
|
145
|
-
- lib/active_record/result.rb
|
146
|
-
- lib/active_record/validations.rb
|
147
|
-
- lib/active_record/callbacks.rb
|
149
|
+
- lib/active_record/attribute_methods/time_zone_conversion.rb
|
150
|
+
- lib/active_record/attribute_methods/write.rb
|
151
|
+
- lib/active_record/attribute_methods.rb
|
148
152
|
- lib/active_record/autosave_association.rb
|
149
153
|
- lib/active_record/base.rb
|
150
|
-
- lib/active_record/
|
151
|
-
- lib/active_record/
|
152
|
-
- lib/active_record/connection_adapters/abstract/
|
153
|
-
- lib/active_record/connection_adapters/abstract/
|
154
|
+
- lib/active_record/callbacks.rb
|
155
|
+
- lib/active_record/coders/yaml_column.rb
|
156
|
+
- lib/active_record/connection_adapters/abstract/connection_pool.rb
|
157
|
+
- lib/active_record/connection_adapters/abstract/connection_specification.rb
|
154
158
|
- lib/active_record/connection_adapters/abstract/database_limits.rb
|
155
|
-
- lib/active_record/connection_adapters/abstract/schema_definitions.rb
|
156
159
|
- lib/active_record/connection_adapters/abstract/database_statements.rb
|
157
|
-
- lib/active_record/connection_adapters/abstract/connection_specification.rb
|
158
|
-
- lib/active_record/connection_adapters/abstract/connection_pool.rb
|
159
160
|
- lib/active_record/connection_adapters/abstract/query_cache.rb
|
161
|
+
- lib/active_record/connection_adapters/abstract/quoting.rb
|
162
|
+
- lib/active_record/connection_adapters/abstract/schema_definitions.rb
|
163
|
+
- lib/active_record/connection_adapters/abstract/schema_statements.rb
|
160
164
|
- lib/active_record/connection_adapters/abstract_adapter.rb
|
161
|
-
- lib/active_record/connection_adapters/sqlite3_adapter.rb
|
162
|
-
- lib/active_record/connection_adapters/mysql_adapter.rb
|
163
165
|
- lib/active_record/connection_adapters/column.rb
|
164
166
|
- lib/active_record/connection_adapters/mysql2_adapter.rb
|
167
|
+
- lib/active_record/connection_adapters/mysql_adapter.rb
|
168
|
+
- lib/active_record/connection_adapters/postgresql_adapter.rb
|
169
|
+
- lib/active_record/connection_adapters/sqlite3_adapter.rb
|
165
170
|
- lib/active_record/connection_adapters/sqlite_adapter.rb
|
166
|
-
- lib/active_record/
|
171
|
+
- lib/active_record/connection_adapters/statement_pool.rb
|
172
|
+
- lib/active_record/counter_cache.rb
|
173
|
+
- lib/active_record/dynamic_finder_match.rb
|
167
174
|
- lib/active_record/dynamic_scope_match.rb
|
168
|
-
- lib/active_record/
|
169
|
-
- lib/active_record/
|
175
|
+
- lib/active_record/errors.rb
|
176
|
+
- lib/active_record/fixtures.rb
|
177
|
+
- lib/active_record/identity_map.rb
|
178
|
+
- lib/active_record/locale/en.yml
|
179
|
+
- lib/active_record/locking/optimistic.rb
|
180
|
+
- lib/active_record/locking/pessimistic.rb
|
181
|
+
- lib/active_record/log_subscriber.rb
|
182
|
+
- lib/active_record/migration/command_recorder.rb
|
183
|
+
- lib/active_record/migration.rb
|
184
|
+
- lib/active_record/named_scope.rb
|
185
|
+
- lib/active_record/nested_attributes.rb
|
186
|
+
- lib/active_record/observer.rb
|
187
|
+
- lib/active_record/persistence.rb
|
170
188
|
- lib/active_record/query_cache.rb
|
189
|
+
- lib/active_record/railtie.rb
|
190
|
+
- lib/active_record/railties/console_sandbox.rb
|
191
|
+
- lib/active_record/railties/controller_runtime.rb
|
192
|
+
- lib/active_record/railties/databases.rake
|
193
|
+
- lib/active_record/railties/jdbcmysql_error.rb
|
194
|
+
- lib/active_record/reflection.rb
|
195
|
+
- lib/active_record/relation/batches.rb
|
196
|
+
- lib/active_record/relation/calculations.rb
|
197
|
+
- lib/active_record/relation/finder_methods.rb
|
198
|
+
- lib/active_record/relation/predicate_builder.rb
|
199
|
+
- lib/active_record/relation/query_methods.rb
|
200
|
+
- lib/active_record/relation/spawn_methods.rb
|
201
|
+
- lib/active_record/relation.rb
|
202
|
+
- lib/active_record/result.rb
|
203
|
+
- lib/active_record/schema.rb
|
204
|
+
- lib/active_record/schema_dumper.rb
|
205
|
+
- lib/active_record/serialization.rb
|
171
206
|
- lib/active_record/serializers/xml_serializer.rb
|
172
|
-
- lib/active_record/
|
173
|
-
- lib/active_record/
|
174
|
-
- lib/active_record/
|
175
|
-
- lib/active_record/
|
176
|
-
- lib/active_record/
|
177
|
-
- lib/active_record/
|
178
|
-
- lib/active_record/
|
179
|
-
- lib/active_record/
|
180
|
-
- lib/active_record
|
181
|
-
- lib/active_record/associations/preloader/singular_association.rb
|
182
|
-
- lib/active_record/associations/preloader/collection_association.rb
|
183
|
-
- lib/active_record/associations/preloader/through_association.rb
|
184
|
-
- lib/active_record/associations/preloader/association.rb
|
185
|
-
- lib/active_record/associations/preloader/belongs_to.rb
|
186
|
-
- lib/active_record/associations/preloader/has_and_belongs_to_many.rb
|
187
|
-
- lib/active_record/associations/preloader/has_one_through.rb
|
188
|
-
- lib/active_record/associations/preloader.rb
|
189
|
-
- lib/active_record/associations/join_helper.rb
|
190
|
-
- lib/active_record/associations/has_many_association.rb
|
191
|
-
- lib/active_record/associations/has_and_belongs_to_many_association.rb
|
192
|
-
- lib/active_record/associations/has_one_association.rb
|
193
|
-
- lib/active_record/associations/collection_association.rb
|
194
|
-
- lib/active_record/associations/join_dependency.rb
|
195
|
-
- lib/active_record/associations/alias_tracker.rb
|
196
|
-
- lib/active_record/associations/through_association.rb
|
197
|
-
- lib/active_record/associations/association.rb
|
198
|
-
- lib/active_record/associations/join_dependency/join_association.rb
|
199
|
-
- lib/active_record/associations/join_dependency/join_part.rb
|
200
|
-
- lib/active_record/associations/join_dependency/join_base.rb
|
201
|
-
- lib/active_record/associations/collection_proxy.rb
|
202
|
-
- lib/active_record/associations/builder/has_one.rb
|
203
|
-
- lib/active_record/associations/builder/has_many.rb
|
204
|
-
- lib/active_record/associations/builder/singular_association.rb
|
205
|
-
- lib/active_record/associations/builder/collection_association.rb
|
206
|
-
- lib/active_record/associations/builder/association.rb
|
207
|
-
- lib/active_record/associations/builder/belongs_to.rb
|
208
|
-
- lib/active_record/associations/builder/has_and_belongs_to_many.rb
|
209
|
-
- lib/rails/generators/active_record/migration.rb
|
210
|
-
- lib/rails/generators/active_record/session_migration/session_migration_generator.rb
|
211
|
-
- lib/rails/generators/active_record/session_migration/templates/migration.rb
|
207
|
+
- lib/active_record/session_store.rb
|
208
|
+
- lib/active_record/test_case.rb
|
209
|
+
- lib/active_record/timestamp.rb
|
210
|
+
- lib/active_record/transactions.rb
|
211
|
+
- lib/active_record/validations/associated.rb
|
212
|
+
- lib/active_record/validations/uniqueness.rb
|
213
|
+
- lib/active_record/validations.rb
|
214
|
+
- lib/active_record/version.rb
|
215
|
+
- lib/active_record.rb
|
212
216
|
- lib/rails/generators/active_record/migration/migration_generator.rb
|
213
217
|
- lib/rails/generators/active_record/migration/templates/migration.rb
|
218
|
+
- lib/rails/generators/active_record/migration.rb
|
214
219
|
- lib/rails/generators/active_record/model/model_generator.rb
|
215
220
|
- lib/rails/generators/active_record/model/templates/migration.rb
|
216
|
-
- lib/rails/generators/active_record/model/templates/module.rb
|
217
221
|
- lib/rails/generators/active_record/model/templates/model.rb
|
218
|
-
- lib/rails/generators/active_record/
|
222
|
+
- lib/rails/generators/active_record/model/templates/module.rb
|
219
223
|
- lib/rails/generators/active_record/observer/observer_generator.rb
|
224
|
+
- lib/rails/generators/active_record/observer/templates/observer.rb
|
225
|
+
- lib/rails/generators/active_record/session_migration/session_migration_generator.rb
|
226
|
+
- lib/rails/generators/active_record/session_migration/templates/migration.rb
|
220
227
|
- lib/rails/generators/active_record.rb
|
221
|
-
- lib/active_record.rb
|
222
228
|
homepage: http://www.rubyonrails.org
|
223
229
|
licenses: []
|
224
230
|
|
@@ -242,16 +248,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
242
248
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
243
249
|
none: false
|
244
250
|
requirements:
|
245
|
-
- - "
|
251
|
+
- - ">"
|
246
252
|
- !ruby/object:Gem::Version
|
247
|
-
hash:
|
253
|
+
hash: 25
|
248
254
|
segments:
|
249
|
-
-
|
250
|
-
|
255
|
+
- 1
|
256
|
+
- 3
|
257
|
+
- 1
|
258
|
+
version: 1.3.1
|
251
259
|
requirements: []
|
252
260
|
|
253
261
|
rubyforge_project:
|
254
|
-
rubygems_version: 1.8.
|
262
|
+
rubygems_version: 1.8.16
|
255
263
|
signing_key:
|
256
264
|
specification_version: 3
|
257
265
|
summary: Object-relational mapper framework (part of Rails).
|