activerecord 4.1.15 → 4.2.0.beta1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +634 -2176
- data/README.rdoc +15 -10
- data/lib/active_record/aggregations.rb +12 -8
- data/lib/active_record/associations/association.rb +1 -1
- data/lib/active_record/associations/association_scope.rb +53 -21
- data/lib/active_record/associations/belongs_to_association.rb +15 -5
- data/lib/active_record/associations/builder/association.rb +16 -5
- data/lib/active_record/associations/builder/belongs_to.rb +7 -29
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +2 -11
- data/lib/active_record/associations/builder/has_one.rb +2 -2
- data/lib/active_record/associations/builder/singular_association.rb +8 -1
- data/lib/active_record/associations/collection_association.rb +32 -44
- data/lib/active_record/associations/collection_proxy.rb +1 -10
- data/lib/active_record/associations/has_many_association.rb +60 -14
- data/lib/active_record/associations/has_many_through_association.rb +34 -23
- data/lib/active_record/associations/has_one_association.rb +0 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +18 -14
- data/lib/active_record/associations/join_dependency.rb +7 -9
- data/lib/active_record/associations/preloader/association.rb +9 -5
- data/lib/active_record/associations/preloader/through_association.rb +3 -3
- data/lib/active_record/associations/preloader.rb +2 -2
- data/lib/active_record/associations/singular_association.rb +16 -1
- data/lib/active_record/associations/through_association.rb +6 -22
- data/lib/active_record/associations.rb +58 -33
- data/lib/active_record/attribute.rb +131 -0
- data/lib/active_record/attribute_assignment.rb +19 -11
- data/lib/active_record/attribute_decorators.rb +66 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +2 -2
- data/lib/active_record/attribute_methods/dirty.rb +85 -42
- data/lib/active_record/attribute_methods/primary_key.rb +6 -8
- data/lib/active_record/attribute_methods/read.rb +14 -57
- data/lib/active_record/attribute_methods/serialization.rb +12 -146
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +32 -40
- data/lib/active_record/attribute_methods/write.rb +8 -23
- data/lib/active_record/attribute_methods.rb +53 -90
- data/lib/active_record/attribute_set/builder.rb +32 -0
- data/lib/active_record/attribute_set.rb +77 -0
- data/lib/active_record/attributes.rb +122 -0
- data/lib/active_record/autosave_association.rb +11 -21
- data/lib/active_record/base.rb +9 -19
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +69 -45
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +22 -42
- data/lib/active_record/connection_adapters/abstract/quoting.rb +59 -60
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +37 -2
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +102 -21
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +9 -33
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +178 -55
- data/lib/active_record/connection_adapters/abstract/transaction.rb +120 -115
- data/lib/active_record/connection_adapters/abstract_adapter.rb +143 -57
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +156 -107
- data/lib/active_record/connection_adapters/column.rb +13 -244
- data/lib/active_record/connection_adapters/connection_specification.rb +6 -20
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -15
- data/lib/active_record/connection_adapters/mysql_adapter.rb +55 -143
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +15 -27
- data/lib/active_record/connection_adapters/postgresql/column.rb +20 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +39 -20
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +96 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +14 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +46 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +11 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +27 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +17 -0
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +21 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +11 -0
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +76 -0
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +11 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +85 -0
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +26 -0
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +29 -388
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +42 -122
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +154 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +86 -34
- data/lib/active_record/connection_adapters/postgresql/utils.rb +66 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +188 -452
- data/lib/active_record/connection_adapters/schema_cache.rb +14 -28
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +54 -47
- data/lib/active_record/connection_handling.rb +1 -1
- data/lib/active_record/core.rb +119 -22
- data/lib/active_record/counter_cache.rb +60 -6
- data/lib/active_record/enum.rb +9 -10
- data/lib/active_record/errors.rb +27 -26
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/fixtures.rb +52 -45
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +33 -8
- data/lib/active_record/integration.rb +4 -4
- data/lib/active_record/locking/optimistic.rb +34 -16
- data/lib/active_record/migration/command_recorder.rb +19 -2
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration.rb +22 -32
- data/lib/active_record/model_schema.rb +39 -48
- data/lib/active_record/nested_attributes.rb +8 -18
- data/lib/active_record/persistence.rb +39 -22
- data/lib/active_record/query_cache.rb +3 -3
- data/lib/active_record/querying.rb +1 -8
- data/lib/active_record/railtie.rb +17 -10
- data/lib/active_record/railties/databases.rake +47 -42
- data/lib/active_record/readonly_attributes.rb +0 -1
- data/lib/active_record/reflection.rb +225 -92
- data/lib/active_record/relation/batches.rb +0 -2
- data/lib/active_record/relation/calculations.rb +28 -32
- data/lib/active_record/relation/delegation.rb +1 -1
- data/lib/active_record/relation/finder_methods.rb +42 -20
- data/lib/active_record/relation/merger.rb +0 -1
- data/lib/active_record/relation/predicate_builder/array_handler.rb +16 -11
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +0 -4
- data/lib/active_record/relation/predicate_builder.rb +1 -22
- data/lib/active_record/relation/query_methods.rb +98 -62
- data/lib/active_record/relation/spawn_methods.rb +6 -7
- data/lib/active_record/relation.rb +35 -11
- data/lib/active_record/result.rb +16 -9
- data/lib/active_record/sanitization.rb +8 -1
- data/lib/active_record/schema.rb +0 -1
- data/lib/active_record/schema_dumper.rb +51 -9
- data/lib/active_record/schema_migration.rb +4 -0
- data/lib/active_record/scoping/default.rb +5 -4
- data/lib/active_record/serializers/xml_serializer.rb +3 -7
- data/lib/active_record/statement_cache.rb +79 -5
- data/lib/active_record/store.rb +5 -5
- data/lib/active_record/tasks/database_tasks.rb +37 -5
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +2 -2
- data/lib/active_record/timestamp.rb +9 -7
- data/lib/active_record/transactions.rb +35 -21
- data/lib/active_record/type/binary.rb +40 -0
- data/lib/active_record/type/boolean.rb +19 -0
- data/lib/active_record/type/date.rb +46 -0
- data/lib/active_record/type/date_time.rb +43 -0
- data/lib/active_record/type/decimal.rb +40 -0
- data/lib/active_record/type/decimal_without_scale.rb +11 -0
- data/lib/active_record/type/float.rb +19 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +19 -0
- data/lib/active_record/type/integer.rb +23 -0
- data/lib/active_record/type/mutable.rb +16 -0
- data/lib/active_record/type/numeric.rb +36 -0
- data/lib/active_record/type/serialized.rb +51 -0
- data/lib/active_record/type/string.rb +36 -0
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +26 -0
- data/lib/active_record/type/time_value.rb +38 -0
- data/lib/active_record/type/type_map.rb +48 -0
- data/lib/active_record/type/value.rb +101 -0
- data/lib/active_record/type.rb +20 -0
- data/lib/active_record/validations/uniqueness.rb +9 -23
- data/lib/active_record/validations.rb +21 -16
- data/lib/active_record.rb +2 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +8 -4
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb +1 -1
- metadata +71 -14
- data/lib/active_record/connection_adapters/postgresql/cast.rb +0 -168
@@ -1,20 +1,7 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module ConnectionAdapters
|
3
|
-
class Transaction #:nodoc:
|
4
|
-
attr_reader :connection
|
5
|
-
|
6
|
-
def initialize(connection)
|
7
|
-
@connection = connection
|
8
|
-
@state = TransactionState.new
|
9
|
-
end
|
10
|
-
|
11
|
-
def state
|
12
|
-
@state
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
3
|
class TransactionState
|
17
|
-
|
4
|
+
attr_reader :parent
|
18
5
|
|
19
6
|
VALID_STATES = Set.new([:committed, :rolledback, nil])
|
20
7
|
|
@@ -35,6 +22,10 @@ module ActiveRecord
|
|
35
22
|
@state == :rolledback
|
36
23
|
end
|
37
24
|
|
25
|
+
def completed?
|
26
|
+
committed? || rolledback?
|
27
|
+
end
|
28
|
+
|
38
29
|
def set_state(state)
|
39
30
|
if !VALID_STATES.include?(state)
|
40
31
|
raise ArgumentError, "Invalid transaction state: #{state}"
|
@@ -43,82 +34,24 @@ module ActiveRecord
|
|
43
34
|
end
|
44
35
|
end
|
45
36
|
|
46
|
-
class
|
47
|
-
def
|
48
|
-
|
49
|
-
end
|
50
|
-
|
51
|
-
def
|
52
|
-
RealTransaction.new(connection, self, options)
|
53
|
-
end
|
54
|
-
|
55
|
-
def closed?
|
56
|
-
true
|
57
|
-
end
|
58
|
-
|
59
|
-
def open?
|
60
|
-
false
|
61
|
-
end
|
62
|
-
|
63
|
-
def joinable?
|
64
|
-
false
|
65
|
-
end
|
66
|
-
|
67
|
-
# This is a noop when there are no open transactions
|
68
|
-
def add_record(record)
|
69
|
-
end
|
37
|
+
class NullTransaction #:nodoc:
|
38
|
+
def initialize; end
|
39
|
+
def closed?; true; end
|
40
|
+
def open?; false; end
|
41
|
+
def joinable?; false; end
|
42
|
+
def add_record(record); end
|
70
43
|
end
|
71
44
|
|
72
|
-
class
|
73
|
-
attr_reader :parent, :records
|
74
|
-
attr_writer :joinable
|
75
|
-
|
76
|
-
def initialize(connection, parent, options = {})
|
77
|
-
super connection
|
78
|
-
|
79
|
-
@parent = parent
|
80
|
-
@records = []
|
81
|
-
@finishing = false
|
82
|
-
@joinable = options.fetch(:joinable, true)
|
83
|
-
end
|
84
|
-
|
85
|
-
# This state is necessary so that we correctly handle stuff that might
|
86
|
-
# happen in a commit/rollback. But it's kinda distasteful. Maybe we can
|
87
|
-
# find a better way to structure it in the future.
|
88
|
-
def finishing?
|
89
|
-
@finishing
|
90
|
-
end
|
91
|
-
|
92
|
-
def joinable?
|
93
|
-
@joinable && !finishing?
|
94
|
-
end
|
95
|
-
|
96
|
-
def number
|
97
|
-
if finishing?
|
98
|
-
parent.number
|
99
|
-
else
|
100
|
-
parent.number + 1
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
def begin(options = {})
|
105
|
-
if finishing?
|
106
|
-
parent.begin
|
107
|
-
else
|
108
|
-
SavepointTransaction.new(connection, self, options)
|
109
|
-
end
|
110
|
-
end
|
45
|
+
class Transaction #:nodoc:
|
111
46
|
|
112
|
-
|
113
|
-
|
114
|
-
perform_rollback
|
115
|
-
parent
|
116
|
-
end
|
47
|
+
attr_reader :connection, :state, :records, :savepoint_name
|
48
|
+
attr_writer :joinable
|
117
49
|
|
118
|
-
def
|
119
|
-
@
|
120
|
-
|
121
|
-
|
50
|
+
def initialize(connection, options)
|
51
|
+
@connection = connection
|
52
|
+
@state = TransactionState.new
|
53
|
+
@records = []
|
54
|
+
@joinable = options.fetch(:joinable, true)
|
122
55
|
end
|
123
56
|
|
124
57
|
def add_record(record)
|
@@ -129,41 +62,82 @@ module ActiveRecord
|
|
129
62
|
end
|
130
63
|
end
|
131
64
|
|
132
|
-
def
|
65
|
+
def rollback
|
133
66
|
@state.set_state(:rolledback)
|
134
|
-
|
67
|
+
end
|
68
|
+
|
69
|
+
def rollback_records
|
70
|
+
ite = records.uniq
|
71
|
+
while record = ite.shift
|
135
72
|
begin
|
136
|
-
record.rolledback!
|
73
|
+
record.rolledback! full_rollback?
|
137
74
|
rescue => e
|
75
|
+
raise if ActiveRecord::Base.raise_in_transactional_callbacks
|
138
76
|
record.logger.error(e) if record.respond_to?(:logger) && record.logger
|
139
77
|
end
|
140
78
|
end
|
79
|
+
ensure
|
80
|
+
ite.each do |i|
|
81
|
+
i.rolledback!(full_rollback?, false)
|
82
|
+
end
|
141
83
|
end
|
142
84
|
|
143
|
-
def
|
85
|
+
def commit
|
144
86
|
@state.set_state(:committed)
|
145
|
-
|
87
|
+
end
|
88
|
+
|
89
|
+
def commit_records
|
90
|
+
ite = records.uniq
|
91
|
+
while record = ite.shift
|
146
92
|
begin
|
147
93
|
record.committed!
|
148
94
|
rescue => e
|
95
|
+
raise if ActiveRecord::Base.raise_in_transactional_callbacks
|
149
96
|
record.logger.error(e) if record.respond_to?(:logger) && record.logger
|
150
97
|
end
|
151
98
|
end
|
99
|
+
ensure
|
100
|
+
ite.each do |i|
|
101
|
+
i.committed!(false)
|
102
|
+
end
|
152
103
|
end
|
153
104
|
|
154
|
-
def
|
155
|
-
|
105
|
+
def full_rollback?; true; end
|
106
|
+
def joinable?; @joinable; end
|
107
|
+
def closed?; false; end
|
108
|
+
def open?; !closed?; end
|
109
|
+
end
|
110
|
+
|
111
|
+
class SavepointTransaction < Transaction
|
112
|
+
|
113
|
+
def initialize(connection, savepoint_name, options)
|
114
|
+
super(connection, options)
|
115
|
+
if options[:isolation]
|
116
|
+
raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction"
|
117
|
+
end
|
118
|
+
connection.create_savepoint(@savepoint_name = savepoint_name)
|
156
119
|
end
|
157
120
|
|
158
|
-
def
|
159
|
-
|
121
|
+
def rollback
|
122
|
+
connection.rollback_to_savepoint(savepoint_name)
|
123
|
+
super
|
124
|
+
rollback_records
|
160
125
|
end
|
161
|
-
end
|
162
126
|
|
163
|
-
|
164
|
-
|
127
|
+
def commit
|
128
|
+
connection.release_savepoint(savepoint_name)
|
165
129
|
super
|
130
|
+
parent = connection.transaction_manager.current_transaction
|
131
|
+
records.each { |r| parent.add_record(r) }
|
132
|
+
end
|
133
|
+
|
134
|
+
def full_rollback?; false; end
|
135
|
+
end
|
166
136
|
|
137
|
+
class RealTransaction < Transaction
|
138
|
+
|
139
|
+
def initialize(connection, options)
|
140
|
+
super
|
167
141
|
if options[:isolation]
|
168
142
|
connection.begin_isolated_db_transaction(options[:isolation])
|
169
143
|
else
|
@@ -171,38 +145,69 @@ module ActiveRecord
|
|
171
145
|
end
|
172
146
|
end
|
173
147
|
|
174
|
-
def
|
148
|
+
def rollback
|
175
149
|
connection.rollback_db_transaction
|
150
|
+
super
|
176
151
|
rollback_records
|
177
152
|
end
|
178
153
|
|
179
|
-
def
|
154
|
+
def commit
|
180
155
|
connection.commit_db_transaction
|
156
|
+
super
|
181
157
|
commit_records
|
182
158
|
end
|
183
159
|
end
|
184
160
|
|
185
|
-
class
|
186
|
-
def initialize(connection
|
187
|
-
|
188
|
-
|
189
|
-
|
161
|
+
class TransactionManager #:nodoc:
|
162
|
+
def initialize(connection)
|
163
|
+
@stack = []
|
164
|
+
@connection = connection
|
165
|
+
end
|
190
166
|
|
191
|
-
|
192
|
-
|
167
|
+
def begin_transaction(options = {})
|
168
|
+
transaction =
|
169
|
+
if @stack.empty?
|
170
|
+
RealTransaction.new(@connection, options)
|
171
|
+
else
|
172
|
+
SavepointTransaction.new(@connection, "active_record_#{@stack.size}", options)
|
173
|
+
end
|
174
|
+
@stack.push(transaction)
|
175
|
+
transaction
|
193
176
|
end
|
194
177
|
|
195
|
-
def
|
196
|
-
|
197
|
-
rollback_records
|
178
|
+
def commit_transaction
|
179
|
+
@stack.pop.commit
|
198
180
|
end
|
199
181
|
|
200
|
-
def
|
201
|
-
@
|
202
|
-
|
203
|
-
|
204
|
-
|
182
|
+
def rollback_transaction
|
183
|
+
@stack.pop.rollback
|
184
|
+
end
|
185
|
+
|
186
|
+
def within_new_transaction(options = {})
|
187
|
+
transaction = begin_transaction options
|
188
|
+
yield
|
189
|
+
rescue Exception => error
|
190
|
+
rollback_transaction if transaction
|
191
|
+
raise
|
192
|
+
ensure
|
193
|
+
begin
|
194
|
+
commit_transaction unless error
|
195
|
+
rescue Exception
|
196
|
+
transaction.rollback unless transaction.state.completed?
|
197
|
+
raise
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def open_transactions
|
202
|
+
@stack.size
|
205
203
|
end
|
204
|
+
|
205
|
+
def current_transaction
|
206
|
+
@stack.last || NULL_TRANSACTION
|
207
|
+
end
|
208
|
+
|
209
|
+
private
|
210
|
+
NULL_TRANSACTION = NullTransaction.new
|
206
211
|
end
|
207
212
|
end
|
208
213
|
end
|
@@ -1,17 +1,23 @@
|
|
1
1
|
require 'date'
|
2
2
|
require 'bigdecimal'
|
3
3
|
require 'bigdecimal/util'
|
4
|
+
require 'active_record/type'
|
4
5
|
require 'active_support/core_ext/benchmark'
|
5
6
|
require 'active_record/connection_adapters/schema_cache'
|
6
7
|
require 'active_record/connection_adapters/abstract/schema_dumper'
|
7
8
|
require 'active_record/connection_adapters/abstract/schema_creation'
|
8
9
|
require 'monitor'
|
10
|
+
require 'arel/collectors/bind'
|
11
|
+
require 'arel/collectors/sql_string'
|
9
12
|
|
10
13
|
module ActiveRecord
|
11
14
|
module ConnectionAdapters # :nodoc:
|
12
15
|
extend ActiveSupport::Autoload
|
13
16
|
|
14
|
-
|
17
|
+
autoload_at 'active_record/connection_adapters/column' do
|
18
|
+
autoload :Column
|
19
|
+
autoload :NullColumn
|
20
|
+
end
|
15
21
|
autoload :ConnectionSpecification
|
16
22
|
|
17
23
|
autoload_at 'active_record/connection_adapters/abstract/schema_definitions' do
|
@@ -39,7 +45,8 @@ module ActiveRecord
|
|
39
45
|
end
|
40
46
|
|
41
47
|
autoload_at 'active_record/connection_adapters/abstract/transaction' do
|
42
|
-
autoload :
|
48
|
+
autoload :TransactionManager
|
49
|
+
autoload :NullTransaction
|
43
50
|
autoload :RealTransaction
|
44
51
|
autoload :SavepointTransaction
|
45
52
|
autoload :TransactionState
|
@@ -71,8 +78,8 @@ module ActiveRecord
|
|
71
78
|
define_callbacks :checkout, :checkin
|
72
79
|
|
73
80
|
attr_accessor :visitor, :pool
|
74
|
-
attr_reader :schema_cache, :
|
75
|
-
alias :in_use? :
|
81
|
+
attr_reader :schema_cache, :owner, :logger
|
82
|
+
alias :in_use? :owner
|
76
83
|
|
77
84
|
def self.type_cast_config_to_integer(config)
|
78
85
|
if config =~ SIMPLE_INT
|
@@ -90,13 +97,14 @@ module ActiveRecord
|
|
90
97
|
end
|
91
98
|
end
|
92
99
|
|
100
|
+
attr_reader :prepared_statements
|
101
|
+
|
93
102
|
def initialize(connection, logger = nil, pool = nil) #:nodoc:
|
94
103
|
super()
|
95
104
|
|
96
105
|
@connection = connection
|
97
|
-
@
|
106
|
+
@owner = nil
|
98
107
|
@instrumenter = ActiveSupport::Notifications.instrumenter
|
99
|
-
@last_use = false
|
100
108
|
@logger = logger
|
101
109
|
@pool = pool
|
102
110
|
@schema_cache = SchemaCache.new self
|
@@ -104,6 +112,26 @@ module ActiveRecord
|
|
104
112
|
@prepared_statements = false
|
105
113
|
end
|
106
114
|
|
115
|
+
class BindCollector < Arel::Collectors::Bind
|
116
|
+
def compile(bvs, conn)
|
117
|
+
super(bvs.map { |bv| conn.quote(*bv.reverse) })
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
class SQLString < Arel::Collectors::SQLString
|
122
|
+
def compile(bvs, conn)
|
123
|
+
super(bvs)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def collector
|
128
|
+
if prepared_statements
|
129
|
+
SQLString.new
|
130
|
+
else
|
131
|
+
BindCollector.new
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
107
135
|
def valid_type?(type)
|
108
136
|
true
|
109
137
|
end
|
@@ -114,9 +142,8 @@ module ActiveRecord
|
|
114
142
|
|
115
143
|
def lease
|
116
144
|
synchronize do
|
117
|
-
unless in_use
|
118
|
-
@
|
119
|
-
@last_use = Time.now
|
145
|
+
unless in_use?
|
146
|
+
@owner = Thread.current
|
120
147
|
end
|
121
148
|
end
|
122
149
|
end
|
@@ -127,19 +154,14 @@ module ActiveRecord
|
|
127
154
|
end
|
128
155
|
|
129
156
|
def expire
|
130
|
-
@
|
131
|
-
end
|
132
|
-
|
133
|
-
def unprepared_visitor
|
134
|
-
self.class::BindSubstitution.new self
|
157
|
+
@owner = nil
|
135
158
|
end
|
136
159
|
|
137
160
|
def unprepared_statement
|
138
161
|
old_prepared_statements, @prepared_statements = @prepared_statements, false
|
139
|
-
old_visitor, @visitor = @visitor, unprepared_visitor
|
140
162
|
yield
|
141
163
|
ensure
|
142
|
-
@
|
164
|
+
@prepared_statements = old_prepared_statements
|
143
165
|
end
|
144
166
|
|
145
167
|
# Returns the human-readable name of the adapter. Use mixed case - one
|
@@ -148,28 +170,19 @@ module ActiveRecord
|
|
148
170
|
'Abstract'
|
149
171
|
end
|
150
172
|
|
151
|
-
# Does this adapter support migrations?
|
152
|
-
# abstract adapter always returns +false+.
|
173
|
+
# Does this adapter support migrations?
|
153
174
|
def supports_migrations?
|
154
175
|
false
|
155
176
|
end
|
156
177
|
|
157
178
|
# Can this adapter determine the primary key for tables not attached
|
158
|
-
# to an Active Record class, such as join tables?
|
159
|
-
# the abstract adapter always returns +false+.
|
179
|
+
# to an Active Record class, such as join tables?
|
160
180
|
def supports_primary_key?
|
161
181
|
false
|
162
182
|
end
|
163
183
|
|
164
|
-
# Does this adapter support using DISTINCT within COUNT? This is +true+
|
165
|
-
# for all adapters except sqlite.
|
166
|
-
def supports_count_distinct?
|
167
|
-
true
|
168
|
-
end
|
169
|
-
|
170
184
|
# Does this adapter support DDL rollbacks in transactions? That is, would
|
171
|
-
# CREATE TABLE or ALTER TABLE get rolled back by a transaction?
|
172
|
-
# SQL Server, and others support this. MySQL and others do not.
|
185
|
+
# CREATE TABLE or ALTER TABLE get rolled back by a transaction?
|
173
186
|
def supports_ddl_transactions?
|
174
187
|
false
|
175
188
|
end
|
@@ -178,8 +191,7 @@ module ActiveRecord
|
|
178
191
|
false
|
179
192
|
end
|
180
193
|
|
181
|
-
# Does this adapter support savepoints?
|
182
|
-
# SQLite < 3.6.8 does not.
|
194
|
+
# Does this adapter support savepoints?
|
183
195
|
def supports_savepoints?
|
184
196
|
false
|
185
197
|
end
|
@@ -187,7 +199,6 @@ module ActiveRecord
|
|
187
199
|
# Should primary key values be selected from their corresponding
|
188
200
|
# sequence before the insert statement? If true, next_sequence_value
|
189
201
|
# is called before each insert to set the record's primary key.
|
190
|
-
# This is false for all adapters but Firebird.
|
191
202
|
def prefetch_primary_key?(table_name = nil)
|
192
203
|
false
|
193
204
|
end
|
@@ -202,8 +213,7 @@ module ActiveRecord
|
|
202
213
|
false
|
203
214
|
end
|
204
215
|
|
205
|
-
# Does this adapter support explain?
|
206
|
-
# mysql2, and postgresql are the only ones that do.
|
216
|
+
# Does this adapter support explain?
|
207
217
|
def supports_explain?
|
208
218
|
false
|
209
219
|
end
|
@@ -213,12 +223,22 @@ module ActiveRecord
|
|
213
223
|
false
|
214
224
|
end
|
215
225
|
|
216
|
-
# Does this adapter support database extensions?
|
217
|
-
# postgresql does.
|
226
|
+
# Does this adapter support database extensions?
|
218
227
|
def supports_extensions?
|
219
228
|
false
|
220
229
|
end
|
221
230
|
|
231
|
+
# Does this adapter support creating indexes in the same statement as
|
232
|
+
# creating the table?
|
233
|
+
def supports_indexes_in_create?
|
234
|
+
false
|
235
|
+
end
|
236
|
+
|
237
|
+
# Does this adapter support creating foreign key constraints?
|
238
|
+
def supports_foreign_keys?
|
239
|
+
false
|
240
|
+
end
|
241
|
+
|
222
242
|
# This is meant to be implemented by the adapters that support extensions
|
223
243
|
def disable_extension(name)
|
224
244
|
end
|
@@ -227,14 +247,12 @@ module ActiveRecord
|
|
227
247
|
def enable_extension(name)
|
228
248
|
end
|
229
249
|
|
230
|
-
# A list of extensions, to be filled in by adapters that support them.
|
231
|
-
# the moment only postgresql does.
|
250
|
+
# A list of extensions, to be filled in by adapters that support them.
|
232
251
|
def extensions
|
233
252
|
[]
|
234
253
|
end
|
235
254
|
|
236
255
|
# A list of index algorithms, to be filled by adapters that support them.
|
237
|
-
# MySQL and PostgreSQL have support for them right now.
|
238
256
|
def index_algorithms
|
239
257
|
{}
|
240
258
|
end
|
@@ -262,12 +280,6 @@ module ActiveRecord
|
|
262
280
|
def active?
|
263
281
|
end
|
264
282
|
|
265
|
-
# Adapter should redefine this if it needs a threadsafe way to approximate
|
266
|
-
# if the connection is active
|
267
|
-
def active_threadsafe?
|
268
|
-
active?
|
269
|
-
end
|
270
|
-
|
271
283
|
# Disconnects from the database if already connected, and establishes a
|
272
284
|
# new connection with the database. Implementors should call super if they
|
273
285
|
# override the default implementation.
|
@@ -301,7 +313,6 @@ module ActiveRecord
|
|
301
313
|
end
|
302
314
|
|
303
315
|
# Returns true if its required to reload the connection between requests for development mode.
|
304
|
-
# This is not the case for Ruby/MySQL and it's not necessary for any adapters except SQLite.
|
305
316
|
def requires_reloading?
|
306
317
|
false
|
307
318
|
end
|
@@ -323,10 +334,6 @@ module ActiveRecord
|
|
323
334
|
@connection
|
324
335
|
end
|
325
336
|
|
326
|
-
def open_transactions
|
327
|
-
@transaction.number
|
328
|
-
end
|
329
|
-
|
330
337
|
def create_savepoint(name = nil)
|
331
338
|
end
|
332
339
|
|
@@ -336,16 +343,22 @@ module ActiveRecord
|
|
336
343
|
def release_savepoint(name = nil)
|
337
344
|
end
|
338
345
|
|
339
|
-
def case_sensitive_modifier(node)
|
346
|
+
def case_sensitive_modifier(node, table_attribute)
|
340
347
|
node
|
341
348
|
end
|
342
349
|
|
350
|
+
def case_sensitive_comparison(table, attribute, column, value)
|
351
|
+
table_attr = table[attribute]
|
352
|
+
value = case_sensitive_modifier(value, table_attr) unless value.nil?
|
353
|
+
table_attr.eq(value)
|
354
|
+
end
|
355
|
+
|
343
356
|
def case_insensitive_comparison(table, attribute, column, value)
|
344
357
|
table[attribute].lower.eq(table.lower(value))
|
345
358
|
end
|
346
359
|
|
347
360
|
def current_savepoint_name
|
348
|
-
|
361
|
+
current_transaction.savepoint_name
|
349
362
|
end
|
350
363
|
|
351
364
|
# Check the connection back in to the connection pool
|
@@ -353,15 +366,82 @@ module ActiveRecord
|
|
353
366
|
pool.checkin self
|
354
367
|
end
|
355
368
|
|
369
|
+
def type_map # :nodoc:
|
370
|
+
@type_map ||= Type::TypeMap.new.tap do |mapping|
|
371
|
+
initialize_type_map(mapping)
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
def new_column(name, default, cast_type, sql_type = nil, null = true)
|
376
|
+
Column.new(name, default, cast_type, sql_type, null)
|
377
|
+
end
|
378
|
+
|
379
|
+
def lookup_cast_type(sql_type) # :nodoc:
|
380
|
+
type_map.lookup(sql_type)
|
381
|
+
end
|
382
|
+
|
356
383
|
protected
|
357
384
|
|
358
|
-
def
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
385
|
+
def initialize_type_map(m) # :nodoc:
|
386
|
+
register_class_with_limit m, %r(boolean)i, Type::Boolean
|
387
|
+
register_class_with_limit m, %r(char)i, Type::String
|
388
|
+
register_class_with_limit m, %r(binary)i, Type::Binary
|
389
|
+
register_class_with_limit m, %r(text)i, Type::Text
|
390
|
+
register_class_with_limit m, %r(date)i, Type::Date
|
391
|
+
register_class_with_limit m, %r(time)i, Type::Time
|
392
|
+
register_class_with_limit m, %r(datetime)i, Type::DateTime
|
393
|
+
register_class_with_limit m, %r(float)i, Type::Float
|
394
|
+
register_class_with_limit m, %r(int)i, Type::Integer
|
395
|
+
|
396
|
+
m.alias_type %r(blob)i, 'binary'
|
397
|
+
m.alias_type %r(clob)i, 'text'
|
398
|
+
m.alias_type %r(timestamp)i, 'datetime'
|
399
|
+
m.alias_type %r(numeric)i, 'decimal'
|
400
|
+
m.alias_type %r(number)i, 'decimal'
|
401
|
+
m.alias_type %r(double)i, 'float'
|
402
|
+
|
403
|
+
m.register_type(%r(decimal)i) do |sql_type|
|
404
|
+
scale = extract_scale(sql_type)
|
405
|
+
precision = extract_precision(sql_type)
|
406
|
+
|
407
|
+
if scale == 0
|
408
|
+
# FIXME: Remove this class as well
|
409
|
+
Type::DecimalWithoutScale.new(precision: precision)
|
410
|
+
else
|
411
|
+
Type::Decimal.new(precision: precision, scale: scale)
|
412
|
+
end
|
363
413
|
end
|
414
|
+
end
|
415
|
+
|
416
|
+
def reload_type_map # :nodoc:
|
417
|
+
type_map.clear
|
418
|
+
initialize_type_map(type_map)
|
419
|
+
end
|
364
420
|
|
421
|
+
def register_class_with_limit(mapping, key, klass) # :nodoc:
|
422
|
+
mapping.register_type(key) do |*args|
|
423
|
+
limit = extract_limit(args.last)
|
424
|
+
klass.new(limit: limit)
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
def extract_scale(sql_type) # :nodoc:
|
429
|
+
case sql_type
|
430
|
+
when /\((\d+)\)/ then 0
|
431
|
+
when /\((\d+)(,(\d+))\)/ then $3.to_i
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
def extract_precision(sql_type) # :nodoc:
|
436
|
+
$1.to_i if sql_type =~ /\((\d+)(,\d+)?\)/
|
437
|
+
end
|
438
|
+
|
439
|
+
def extract_limit(sql_type) # :nodoc:
|
440
|
+
$1.to_i if sql_type =~ /\((.*)\)/
|
441
|
+
end
|
442
|
+
|
443
|
+
def translate_exception_class(e, sql)
|
444
|
+
message = "#{e.class.name}: #{e.message}: #{sql}"
|
365
445
|
@logger.error message if @logger
|
366
446
|
exception = translate_exception(e, message)
|
367
447
|
exception.set_backtrace e.backtrace
|
@@ -386,7 +466,13 @@ module ActiveRecord
|
|
386
466
|
end
|
387
467
|
|
388
468
|
def without_prepared_statement?(binds)
|
389
|
-
|
469
|
+
!prepared_statements || binds.empty?
|
470
|
+
end
|
471
|
+
|
472
|
+
def column_for(table_name, column_name) # :nodoc:
|
473
|
+
column_name = column_name.to_s
|
474
|
+
columns(table_name).detect { |c| c.name == column_name } ||
|
475
|
+
raise(ActiveRecordError, "No such column: #{table_name}.#{column_name}")
|
390
476
|
end
|
391
477
|
end
|
392
478
|
end
|