activerecord 3.0.0 → 4.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +2102 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +35 -44
- data/examples/performance.rb +110 -100
- data/lib/active_record/aggregations.rb +59 -75
- data/lib/active_record/associations/alias_tracker.rb +76 -0
- data/lib/active_record/associations/association.rb +248 -0
- data/lib/active_record/associations/association_scope.rb +135 -0
- data/lib/active_record/associations/belongs_to_association.rb +60 -59
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +16 -59
- data/lib/active_record/associations/builder/association.rb +108 -0
- data/lib/active_record/associations/builder/belongs_to.rb +98 -0
- data/lib/active_record/associations/builder/collection_association.rb +89 -0
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +39 -0
- data/lib/active_record/associations/builder/has_many.rb +15 -0
- data/lib/active_record/associations/builder/has_one.rb +25 -0
- data/lib/active_record/associations/builder/singular_association.rb +32 -0
- data/lib/active_record/associations/collection_association.rb +608 -0
- data/lib/active_record/associations/collection_proxy.rb +986 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +40 -112
- data/lib/active_record/associations/has_many_association.rb +83 -76
- data/lib/active_record/associations/has_many_through_association.rb +147 -66
- data/lib/active_record/associations/has_one_association.rb +67 -108
- data/lib/active_record/associations/has_one_through_association.rb +21 -25
- data/lib/active_record/associations/join_dependency/join_association.rb +174 -0
- data/lib/active_record/associations/join_dependency/join_base.rb +24 -0
- data/lib/active_record/associations/join_dependency/join_part.rb +78 -0
- data/lib/active_record/associations/join_dependency.rb +235 -0
- data/lib/active_record/associations/join_helper.rb +45 -0
- data/lib/active_record/associations/preloader/association.rb +121 -0
- data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
- data/lib/active_record/associations/preloader/collection_association.rb +24 -0
- data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +60 -0
- data/lib/active_record/associations/preloader/has_many.rb +17 -0
- data/lib/active_record/associations/preloader/has_many_through.rb +19 -0
- data/lib/active_record/associations/preloader/has_one.rb +23 -0
- data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
- data/lib/active_record/associations/preloader/singular_association.rb +21 -0
- data/lib/active_record/associations/preloader/through_association.rb +63 -0
- data/lib/active_record/associations/preloader.rb +178 -0
- data/lib/active_record/associations/singular_association.rb +64 -0
- data/lib/active_record/associations/through_association.rb +87 -0
- data/lib/active_record/associations.rb +512 -1224
- data/lib/active_record/attribute_assignment.rb +201 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +49 -12
- data/lib/active_record/attribute_methods/dirty.rb +51 -28
- data/lib/active_record/attribute_methods/primary_key.rb +94 -22
- data/lib/active_record/attribute_methods/query.rb +5 -4
- data/lib/active_record/attribute_methods/read.rb +63 -72
- data/lib/active_record/attribute_methods/serialization.rb +162 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -41
- data/lib/active_record/attribute_methods/write.rb +39 -13
- data/lib/active_record/attribute_methods.rb +362 -29
- data/lib/active_record/autosave_association.rb +132 -75
- data/lib/active_record/base.rb +83 -1627
- data/lib/active_record/callbacks.rb +69 -47
- data/lib/active_record/coders/yaml_column.rb +38 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +411 -138
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +21 -11
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +234 -173
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +36 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +82 -25
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +176 -414
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +70 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +562 -232
- data/lib/active_record/connection_adapters/abstract/transaction.rb +203 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +281 -53
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +782 -0
- data/lib/active_record/connection_adapters/column.rb +318 -0
- data/lib/active_record/connection_adapters/connection_specification.rb +96 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +273 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +365 -450
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +97 -0
- data/lib/active_record/connection_adapters/postgresql/cast.rb +152 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +242 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +366 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +171 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +489 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +672 -752
- data/lib/active_record/connection_adapters/schema_cache.rb +129 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +588 -17
- data/lib/active_record/connection_adapters/statement_pool.rb +40 -0
- data/lib/active_record/connection_handling.rb +98 -0
- data/lib/active_record/core.rb +463 -0
- data/lib/active_record/counter_cache.rb +108 -101
- data/lib/active_record/dynamic_matchers.rb +131 -0
- data/lib/active_record/errors.rb +54 -13
- data/lib/active_record/explain.rb +38 -0
- data/lib/active_record/explain_registry.rb +30 -0
- data/lib/active_record/explain_subscriber.rb +29 -0
- data/lib/active_record/fixture_set/file.rb +55 -0
- data/lib/active_record/fixtures.rb +703 -785
- data/lib/active_record/inheritance.rb +200 -0
- data/lib/active_record/integration.rb +60 -0
- data/lib/active_record/locale/en.yml +8 -1
- data/lib/active_record/locking/optimistic.rb +69 -60
- data/lib/active_record/locking/pessimistic.rb +34 -12
- data/lib/active_record/log_subscriber.rb +40 -6
- data/lib/active_record/migration/command_recorder.rb +164 -0
- data/lib/active_record/migration/join_table.rb +15 -0
- data/lib/active_record/migration.rb +614 -216
- data/lib/active_record/model_schema.rb +345 -0
- data/lib/active_record/nested_attributes.rb +248 -119
- data/lib/active_record/null_relation.rb +65 -0
- data/lib/active_record/persistence.rb +275 -57
- data/lib/active_record/query_cache.rb +29 -9
- data/lib/active_record/querying.rb +62 -0
- data/lib/active_record/railtie.rb +135 -21
- data/lib/active_record/railties/console_sandbox.rb +5 -0
- data/lib/active_record/railties/controller_runtime.rb +17 -5
- data/lib/active_record/railties/databases.rake +249 -359
- data/lib/active_record/railties/jdbcmysql_error.rb +16 -0
- data/lib/active_record/readonly_attributes.rb +30 -0
- data/lib/active_record/reflection.rb +283 -103
- data/lib/active_record/relation/batches.rb +38 -34
- data/lib/active_record/relation/calculations.rb +252 -139
- data/lib/active_record/relation/delegation.rb +125 -0
- data/lib/active_record/relation/finder_methods.rb +182 -188
- data/lib/active_record/relation/merger.rb +161 -0
- data/lib/active_record/relation/predicate_builder.rb +86 -21
- data/lib/active_record/relation/query_methods.rb +917 -134
- data/lib/active_record/relation/spawn_methods.rb +53 -92
- data/lib/active_record/relation.rb +405 -143
- data/lib/active_record/result.rb +67 -0
- data/lib/active_record/runtime_registry.rb +17 -0
- data/lib/active_record/sanitization.rb +168 -0
- data/lib/active_record/schema.rb +20 -14
- data/lib/active_record/schema_dumper.rb +55 -46
- data/lib/active_record/schema_migration.rb +39 -0
- data/lib/active_record/scoping/default.rb +146 -0
- data/lib/active_record/scoping/named.rb +175 -0
- data/lib/active_record/scoping.rb +82 -0
- data/lib/active_record/serialization.rb +8 -46
- data/lib/active_record/serializers/xml_serializer.rb +21 -68
- data/lib/active_record/statement_cache.rb +26 -0
- data/lib/active_record/store.rb +156 -0
- data/lib/active_record/tasks/database_tasks.rb +203 -0
- data/lib/active_record/tasks/firebird_database_tasks.rb +56 -0
- data/lib/active_record/tasks/mysql_database_tasks.rb +143 -0
- data/lib/active_record/tasks/oracle_database_tasks.rb +45 -0
- data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
- data/lib/active_record/tasks/sqlite_database_tasks.rb +51 -0
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +48 -0
- data/lib/active_record/test_case.rb +57 -28
- data/lib/active_record/timestamp.rb +49 -18
- data/lib/active_record/transactions.rb +106 -63
- data/lib/active_record/translation.rb +22 -0
- data/lib/active_record/validations/associated.rb +25 -24
- data/lib/active_record/validations/presence.rb +65 -0
- data/lib/active_record/validations/uniqueness.rb +123 -83
- data/lib/active_record/validations.rb +29 -29
- data/lib/active_record/version.rb +7 -5
- data/lib/active_record.rb +83 -34
- data/lib/rails/generators/active_record/migration/migration_generator.rb +46 -9
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +19 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb +30 -8
- data/lib/rails/generators/active_record/model/model_generator.rb +15 -5
- data/lib/rails/generators/active_record/model/templates/model.rb +7 -2
- data/lib/rails/generators/active_record/model/templates/module.rb +3 -1
- data/lib/rails/generators/active_record.rb +4 -8
- metadata +163 -121
- data/CHANGELOG +0 -6023
- data/examples/associations.png +0 -0
- data/lib/active_record/association_preload.rb +0 -403
- data/lib/active_record/associations/association_collection.rb +0 -562
- data/lib/active_record/associations/association_proxy.rb +0 -295
- data/lib/active_record/associations/through_association_scope.rb +0 -154
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -113
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -401
- data/lib/active_record/dynamic_finder_match.rb +0 -53
- data/lib/active_record/dynamic_scope_match.rb +0 -32
- data/lib/active_record/named_scope.rb +0 -138
- data/lib/active_record/observer.rb +0 -140
- data/lib/active_record/session_store.rb +0 -340
- data/lib/rails/generators/active_record/model/templates/migration.rb +0 -16
- data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
- data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -2
- data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -24
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -16
@@ -0,0 +1,203 @@
|
|
1
|
+
module ActiveRecord
|
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
|
+
class TransactionState
|
17
|
+
attr_accessor :parent
|
18
|
+
|
19
|
+
VALID_STATES = Set.new([:committed, :rolledback, nil])
|
20
|
+
|
21
|
+
def initialize(state = nil)
|
22
|
+
@state = state
|
23
|
+
@parent = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def committed?
|
27
|
+
@state == :committed
|
28
|
+
end
|
29
|
+
|
30
|
+
def rolledback?
|
31
|
+
@state == :rolledback
|
32
|
+
end
|
33
|
+
|
34
|
+
def set_state(state)
|
35
|
+
if !VALID_STATES.include?(state)
|
36
|
+
raise ArgumentError, "Invalid transaction state: #{state}"
|
37
|
+
end
|
38
|
+
@state = state
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class ClosedTransaction < Transaction #:nodoc:
|
43
|
+
def number
|
44
|
+
0
|
45
|
+
end
|
46
|
+
|
47
|
+
def begin(options = {})
|
48
|
+
RealTransaction.new(connection, self, options)
|
49
|
+
end
|
50
|
+
|
51
|
+
def closed?
|
52
|
+
true
|
53
|
+
end
|
54
|
+
|
55
|
+
def open?
|
56
|
+
false
|
57
|
+
end
|
58
|
+
|
59
|
+
def joinable?
|
60
|
+
false
|
61
|
+
end
|
62
|
+
|
63
|
+
# This is a noop when there are no open transactions
|
64
|
+
def add_record(record)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class OpenTransaction < Transaction #:nodoc:
|
69
|
+
attr_reader :parent, :records
|
70
|
+
attr_writer :joinable
|
71
|
+
|
72
|
+
def initialize(connection, parent, options = {})
|
73
|
+
super connection
|
74
|
+
|
75
|
+
@parent = parent
|
76
|
+
@records = []
|
77
|
+
@finishing = false
|
78
|
+
@joinable = options.fetch(:joinable, true)
|
79
|
+
end
|
80
|
+
|
81
|
+
# This state is necessary so that we correctly handle stuff that might
|
82
|
+
# happen in a commit/rollback. But it's kinda distasteful. Maybe we can
|
83
|
+
# find a better way to structure it in the future.
|
84
|
+
def finishing?
|
85
|
+
@finishing
|
86
|
+
end
|
87
|
+
|
88
|
+
def joinable?
|
89
|
+
@joinable && !finishing?
|
90
|
+
end
|
91
|
+
|
92
|
+
def number
|
93
|
+
if finishing?
|
94
|
+
parent.number
|
95
|
+
else
|
96
|
+
parent.number + 1
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def begin(options = {})
|
101
|
+
if finishing?
|
102
|
+
parent.begin
|
103
|
+
else
|
104
|
+
SavepointTransaction.new(connection, self, options)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def rollback
|
109
|
+
@finishing = true
|
110
|
+
perform_rollback
|
111
|
+
parent
|
112
|
+
end
|
113
|
+
|
114
|
+
def commit
|
115
|
+
@finishing = true
|
116
|
+
perform_commit
|
117
|
+
parent
|
118
|
+
end
|
119
|
+
|
120
|
+
def add_record(record)
|
121
|
+
if record.has_transactional_callbacks?
|
122
|
+
records << record
|
123
|
+
else
|
124
|
+
record.set_transaction_state(@state)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def rollback_records
|
129
|
+
@state.set_state(:rolledback)
|
130
|
+
records.uniq.each do |record|
|
131
|
+
begin
|
132
|
+
record.rolledback!(parent.closed?)
|
133
|
+
rescue => e
|
134
|
+
record.logger.error(e) if record.respond_to?(:logger) && record.logger
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def commit_records
|
140
|
+
@state.set_state(:committed)
|
141
|
+
records.uniq.each do |record|
|
142
|
+
begin
|
143
|
+
record.committed!
|
144
|
+
rescue => e
|
145
|
+
record.logger.error(e) if record.respond_to?(:logger) && record.logger
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def closed?
|
151
|
+
false
|
152
|
+
end
|
153
|
+
|
154
|
+
def open?
|
155
|
+
true
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
class RealTransaction < OpenTransaction #:nodoc:
|
160
|
+
def initialize(connection, parent, options = {})
|
161
|
+
super
|
162
|
+
|
163
|
+
if options[:isolation]
|
164
|
+
connection.begin_isolated_db_transaction(options[:isolation])
|
165
|
+
else
|
166
|
+
connection.begin_db_transaction
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def perform_rollback
|
171
|
+
connection.rollback_db_transaction
|
172
|
+
rollback_records
|
173
|
+
end
|
174
|
+
|
175
|
+
def perform_commit
|
176
|
+
connection.commit_db_transaction
|
177
|
+
commit_records
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
class SavepointTransaction < OpenTransaction #:nodoc:
|
182
|
+
def initialize(connection, parent, options = {})
|
183
|
+
if options[:isolation]
|
184
|
+
raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction"
|
185
|
+
end
|
186
|
+
|
187
|
+
super
|
188
|
+
connection.create_savepoint
|
189
|
+
end
|
190
|
+
|
191
|
+
def perform_rollback
|
192
|
+
connection.rollback_to_savepoint
|
193
|
+
rollback_records
|
194
|
+
end
|
195
|
+
|
196
|
+
def perform_commit
|
197
|
+
@state.set_state(:committed)
|
198
|
+
@state.parent = parent.state
|
199
|
+
connection.release_savepoint
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
@@ -2,19 +2,45 @@ require 'date'
|
|
2
2
|
require 'bigdecimal'
|
3
3
|
require 'bigdecimal/util'
|
4
4
|
require 'active_support/core_ext/benchmark'
|
5
|
-
|
6
|
-
|
7
|
-
require '
|
8
|
-
require 'active_record/connection_adapters/abstract/schema_statements'
|
9
|
-
require 'active_record/connection_adapters/abstract/database_statements'
|
10
|
-
require 'active_record/connection_adapters/abstract/quoting'
|
11
|
-
require 'active_record/connection_adapters/abstract/connection_pool'
|
12
|
-
require 'active_record/connection_adapters/abstract/connection_specification'
|
13
|
-
require 'active_record/connection_adapters/abstract/query_cache'
|
14
|
-
require 'active_record/connection_adapters/abstract/database_limits'
|
5
|
+
require 'active_record/connection_adapters/schema_cache'
|
6
|
+
require 'active_record/connection_adapters/abstract/schema_dumper'
|
7
|
+
require 'monitor'
|
15
8
|
|
16
9
|
module ActiveRecord
|
17
10
|
module ConnectionAdapters # :nodoc:
|
11
|
+
extend ActiveSupport::Autoload
|
12
|
+
|
13
|
+
autoload :Column
|
14
|
+
autoload :ConnectionSpecification
|
15
|
+
|
16
|
+
autoload_at 'active_record/connection_adapters/abstract/schema_definitions' do
|
17
|
+
autoload :IndexDefinition
|
18
|
+
autoload :ColumnDefinition
|
19
|
+
autoload :TableDefinition
|
20
|
+
autoload :Table
|
21
|
+
autoload :AlterTable
|
22
|
+
end
|
23
|
+
|
24
|
+
autoload_at 'active_record/connection_adapters/abstract/connection_pool' do
|
25
|
+
autoload :ConnectionHandler
|
26
|
+
autoload :ConnectionManagement
|
27
|
+
end
|
28
|
+
|
29
|
+
autoload_under 'abstract' do
|
30
|
+
autoload :SchemaStatements
|
31
|
+
autoload :DatabaseStatements
|
32
|
+
autoload :DatabaseLimits
|
33
|
+
autoload :Quoting
|
34
|
+
autoload :ConnectionPool
|
35
|
+
autoload :QueryCache
|
36
|
+
end
|
37
|
+
|
38
|
+
autoload_at 'active_record/connection_adapters/abstract/transaction' do
|
39
|
+
autoload :ClosedTransaction
|
40
|
+
autoload :RealTransaction
|
41
|
+
autoload :SavepointTransaction
|
42
|
+
end
|
43
|
+
|
18
44
|
# Active Record supports multiple database systems. AbstractAdapter and
|
19
45
|
# related classes form the abstraction layer which makes this possible.
|
20
46
|
# An AbstractAdapter represents a connection to a database, and provides an
|
@@ -33,68 +59,245 @@ module ActiveRecord
|
|
33
59
|
include DatabaseLimits
|
34
60
|
include QueryCache
|
35
61
|
include ActiveSupport::Callbacks
|
62
|
+
include MonitorMixin
|
63
|
+
include ColumnDumper
|
64
|
+
|
65
|
+
SIMPLE_INT = /\A\d+\z/
|
36
66
|
|
37
67
|
define_callbacks :checkout, :checkin
|
38
68
|
|
39
|
-
|
40
|
-
|
41
|
-
|
69
|
+
attr_accessor :visitor, :pool
|
70
|
+
attr_reader :schema_cache, :last_use, :in_use, :logger
|
71
|
+
alias :in_use? :in_use
|
72
|
+
|
73
|
+
def self.type_cast_config_to_integer(config)
|
74
|
+
if config =~ SIMPLE_INT
|
75
|
+
config.to_i
|
76
|
+
else
|
77
|
+
config
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.type_cast_config_to_boolean(config)
|
82
|
+
if config == "false"
|
83
|
+
false
|
84
|
+
else
|
85
|
+
config
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def initialize(connection, logger = nil, pool = nil) #:nodoc:
|
90
|
+
super()
|
91
|
+
|
92
|
+
@connection = connection
|
93
|
+
@in_use = false
|
94
|
+
@instrumenter = ActiveSupport::Notifications.instrumenter
|
95
|
+
@last_use = false
|
96
|
+
@logger = logger
|
97
|
+
@pool = pool
|
98
|
+
@query_cache = Hash.new { |h,sql| h[sql] = {} }
|
42
99
|
@query_cache_enabled = false
|
43
|
-
@
|
44
|
-
@
|
100
|
+
@schema_cache = SchemaCache.new self
|
101
|
+
@visitor = nil
|
102
|
+
end
|
103
|
+
|
104
|
+
def valid_type?(type)
|
105
|
+
true
|
106
|
+
end
|
107
|
+
|
108
|
+
class SchemaCreation
|
109
|
+
def initialize(conn)
|
110
|
+
@conn = conn
|
111
|
+
@cache = {}
|
112
|
+
end
|
113
|
+
|
114
|
+
def accept(o)
|
115
|
+
m = @cache[o.class] ||= "visit_#{o.class.name.split('::').last}"
|
116
|
+
send m, o
|
117
|
+
end
|
118
|
+
|
119
|
+
private
|
120
|
+
|
121
|
+
def visit_AlterTable(o)
|
122
|
+
sql = "ALTER TABLE #{quote_table_name(o.name)} "
|
123
|
+
sql << o.adds.map { |col| visit_AddColumn col }.join(' ')
|
124
|
+
end
|
125
|
+
|
126
|
+
def visit_AddColumn(o)
|
127
|
+
sql_type = type_to_sql(o.type.to_sym, o.limit, o.precision, o.scale)
|
128
|
+
sql = "ADD #{quote_column_name(o.name)} #{sql_type}"
|
129
|
+
add_column_options!(sql, column_options(o))
|
130
|
+
end
|
131
|
+
|
132
|
+
def visit_ColumnDefinition(o)
|
133
|
+
sql_type = type_to_sql(o.type.to_sym, o.limit, o.precision, o.scale)
|
134
|
+
column_sql = "#{quote_column_name(o.name)} #{sql_type}"
|
135
|
+
add_column_options!(column_sql, column_options(o)) unless o.primary_key?
|
136
|
+
column_sql
|
137
|
+
end
|
138
|
+
|
139
|
+
def visit_TableDefinition(o)
|
140
|
+
create_sql = "CREATE#{' TEMPORARY' if o.temporary} TABLE "
|
141
|
+
create_sql << "#{quote_table_name(o.name)} ("
|
142
|
+
create_sql << o.columns.map { |c| accept c }.join(', ')
|
143
|
+
create_sql << ") #{o.options}"
|
144
|
+
create_sql
|
145
|
+
end
|
146
|
+
|
147
|
+
def column_options(o)
|
148
|
+
column_options = {}
|
149
|
+
column_options[:null] = o.null unless o.null.nil?
|
150
|
+
column_options[:default] = o.default unless o.default.nil?
|
151
|
+
column_options[:column] = o
|
152
|
+
column_options
|
153
|
+
end
|
154
|
+
|
155
|
+
def quote_column_name(name)
|
156
|
+
@conn.quote_column_name name
|
157
|
+
end
|
158
|
+
|
159
|
+
def quote_table_name(name)
|
160
|
+
@conn.quote_table_name name
|
161
|
+
end
|
162
|
+
|
163
|
+
def type_to_sql(type, limit, precision, scale)
|
164
|
+
@conn.type_to_sql type.to_sym, limit, precision, scale
|
165
|
+
end
|
166
|
+
|
167
|
+
def add_column_options!(column_sql, column_options)
|
168
|
+
@conn.add_column_options! column_sql, column_options
|
169
|
+
column_sql
|
170
|
+
end
|
45
171
|
end
|
46
172
|
|
47
|
-
|
173
|
+
def schema_creation
|
174
|
+
SchemaCreation.new self
|
175
|
+
end
|
176
|
+
|
177
|
+
def lease
|
178
|
+
synchronize do
|
179
|
+
unless in_use
|
180
|
+
@in_use = true
|
181
|
+
@last_use = Time.now
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def schema_cache=(cache)
|
187
|
+
cache.connection = self
|
188
|
+
@schema_cache = cache
|
189
|
+
end
|
190
|
+
|
191
|
+
def expire
|
192
|
+
@in_use = false
|
193
|
+
end
|
194
|
+
|
195
|
+
def unprepared_visitor
|
196
|
+
self.class::BindSubstitution.new self
|
197
|
+
end
|
198
|
+
|
199
|
+
def unprepared_statement
|
200
|
+
old, @visitor = @visitor, unprepared_visitor
|
201
|
+
yield
|
202
|
+
ensure
|
203
|
+
@visitor = old
|
204
|
+
end
|
205
|
+
|
206
|
+
# Returns the human-readable name of the adapter. Use mixed case - one
|
48
207
|
# can always use downcase if needed.
|
49
208
|
def adapter_name
|
50
209
|
'Abstract'
|
51
210
|
end
|
52
211
|
|
53
|
-
# Does this adapter support migrations?
|
212
|
+
# Does this adapter support migrations? Backend specific, as the
|
54
213
|
# abstract adapter always returns +false+.
|
55
214
|
def supports_migrations?
|
56
215
|
false
|
57
216
|
end
|
58
217
|
|
59
218
|
# Can this adapter determine the primary key for tables not attached
|
60
|
-
# to an Active Record class, such as join tables?
|
219
|
+
# to an Active Record class, such as join tables? Backend specific, as
|
61
220
|
# the abstract adapter always returns +false+.
|
62
221
|
def supports_primary_key?
|
63
222
|
false
|
64
223
|
end
|
65
224
|
|
66
|
-
# Does this adapter support using DISTINCT within COUNT?
|
225
|
+
# Does this adapter support using DISTINCT within COUNT? This is +true+
|
67
226
|
# for all adapters except sqlite.
|
68
227
|
def supports_count_distinct?
|
69
228
|
true
|
70
229
|
end
|
71
230
|
|
72
|
-
# Does this adapter support DDL rollbacks in transactions?
|
73
|
-
# CREATE TABLE or ALTER TABLE get rolled back by a transaction?
|
74
|
-
# SQL Server, and others support this.
|
231
|
+
# Does this adapter support DDL rollbacks in transactions? That is, would
|
232
|
+
# CREATE TABLE or ALTER TABLE get rolled back by a transaction? PostgreSQL,
|
233
|
+
# SQL Server, and others support this. MySQL and others do not.
|
75
234
|
def supports_ddl_transactions?
|
76
235
|
false
|
77
236
|
end
|
78
237
|
|
79
|
-
|
80
|
-
|
238
|
+
def supports_bulk_alter?
|
239
|
+
false
|
240
|
+
end
|
241
|
+
|
242
|
+
# Does this adapter support savepoints? PostgreSQL and MySQL do,
|
243
|
+
# SQLite < 3.6.8 does not.
|
81
244
|
def supports_savepoints?
|
82
245
|
false
|
83
246
|
end
|
84
247
|
|
85
248
|
# Should primary key values be selected from their corresponding
|
86
|
-
# sequence before the insert statement?
|
249
|
+
# sequence before the insert statement? If true, next_sequence_value
|
87
250
|
# is called before each insert to set the record's primary key.
|
88
251
|
# This is false for all adapters but Firebird.
|
89
252
|
def prefetch_primary_key?(table_name = nil)
|
90
253
|
false
|
91
254
|
end
|
92
255
|
|
256
|
+
# Does this adapter support index sort order?
|
257
|
+
def supports_index_sort_order?
|
258
|
+
false
|
259
|
+
end
|
260
|
+
|
261
|
+
# Does this adapter support partial indices?
|
262
|
+
def supports_partial_index?
|
263
|
+
false
|
264
|
+
end
|
265
|
+
|
266
|
+
# Does this adapter support explain? As of this writing sqlite3,
|
267
|
+
# mysql2, and postgresql are the only ones that do.
|
268
|
+
def supports_explain?
|
269
|
+
false
|
270
|
+
end
|
271
|
+
|
272
|
+
# Does this adapter support setting the isolation level for a transaction?
|
273
|
+
def supports_transaction_isolation?
|
274
|
+
false
|
275
|
+
end
|
276
|
+
|
277
|
+
# Does this adapter support database extensions? As of this writing only
|
278
|
+
# postgresql does.
|
279
|
+
def supports_extensions?
|
280
|
+
false
|
281
|
+
end
|
282
|
+
|
283
|
+
# A list of extensions, to be filled in by adapters that support them. At
|
284
|
+
# the moment only postgresql does.
|
285
|
+
def extensions
|
286
|
+
[]
|
287
|
+
end
|
288
|
+
|
289
|
+
# A list of index algorithms, to be filled by adapters that support them.
|
290
|
+
# MySQL and PostgreSQL have support for them right now.
|
291
|
+
def index_algorithms
|
292
|
+
{}
|
293
|
+
end
|
294
|
+
|
93
295
|
# QUOTING ==================================================
|
94
296
|
|
95
|
-
#
|
96
|
-
|
97
|
-
|
297
|
+
# Returns a bind substitution value given a +column+ and list of current
|
298
|
+
# +binds+.
|
299
|
+
def substitute_at(column, index)
|
300
|
+
Arel::Nodes::BindParam.new '?'
|
98
301
|
end
|
99
302
|
|
100
303
|
# REFERENTIAL INTEGRITY ====================================
|
@@ -110,19 +313,21 @@ module ActiveRecord
|
|
110
313
|
# checking whether the database is actually capable of responding, i.e. whether
|
111
314
|
# the connection isn't stale.
|
112
315
|
def active?
|
113
|
-
@active != false
|
114
316
|
end
|
115
317
|
|
116
318
|
# Disconnects from the database if already connected, and establishes a
|
117
|
-
# new connection with the database.
|
319
|
+
# new connection with the database. Implementors should call super if they
|
320
|
+
# override the default implementation.
|
118
321
|
def reconnect!
|
119
|
-
|
322
|
+
clear_cache!
|
323
|
+
reset_transaction
|
120
324
|
end
|
121
325
|
|
122
326
|
# Disconnects from the database if already connected. Otherwise, this
|
123
327
|
# method does nothing.
|
124
328
|
def disconnect!
|
125
|
-
|
329
|
+
clear_cache!
|
330
|
+
reset_transaction
|
126
331
|
end
|
127
332
|
|
128
333
|
# Reset the state of this connection, directing the DBMS to clear
|
@@ -135,6 +340,13 @@ module ActiveRecord
|
|
135
340
|
# this should be overridden by concrete adapters
|
136
341
|
end
|
137
342
|
|
343
|
+
###
|
344
|
+
# Clear any caching the database adapter may be doing, for example
|
345
|
+
# clearing the prepared statement cache. This is database specific.
|
346
|
+
def clear_cache!
|
347
|
+
# this should be overridden by concrete adapters
|
348
|
+
end
|
349
|
+
|
138
350
|
# Returns true if its required to reload the connection between requests for development mode.
|
139
351
|
# This is not the case for Ruby/MySQL and it's not necessary for any adapters except SQLite.
|
140
352
|
def requires_reloading?
|
@@ -159,20 +371,21 @@ module ActiveRecord
|
|
159
371
|
end
|
160
372
|
|
161
373
|
def open_transactions
|
162
|
-
@
|
374
|
+
@transaction.number
|
163
375
|
end
|
164
376
|
|
165
377
|
def increment_open_transactions
|
166
|
-
|
167
|
-
@open_transactions += 1
|
378
|
+
ActiveSupport::Deprecation.warn "#increment_open_transactions is deprecated and has no effect"
|
168
379
|
end
|
169
380
|
|
170
381
|
def decrement_open_transactions
|
171
|
-
|
382
|
+
ActiveSupport::Deprecation.warn "#decrement_open_transactions is deprecated and has no effect"
|
172
383
|
end
|
173
384
|
|
174
385
|
def transaction_joinable=(joinable)
|
175
|
-
|
386
|
+
message = "#transaction_joinable= is deprecated. Please pass the :joinable option to #begin_transaction instead."
|
387
|
+
ActiveSupport::Deprecation.warn message
|
388
|
+
@transaction.joinable = joinable
|
176
389
|
end
|
177
390
|
|
178
391
|
def create_savepoint
|
@@ -184,29 +397,44 @@ module ActiveRecord
|
|
184
397
|
def release_savepoint
|
185
398
|
end
|
186
399
|
|
400
|
+
def case_sensitive_modifier(node)
|
401
|
+
node
|
402
|
+
end
|
403
|
+
|
404
|
+
def case_insensitive_comparison(table, attribute, column, value)
|
405
|
+
table[attribute].lower.eq(table.lower(value))
|
406
|
+
end
|
407
|
+
|
187
408
|
def current_savepoint_name
|
188
409
|
"active_record_#{open_transactions}"
|
189
410
|
end
|
190
411
|
|
191
|
-
|
412
|
+
# Check the connection back in to the connection pool
|
413
|
+
def close
|
414
|
+
pool.checkin self
|
415
|
+
end
|
192
416
|
|
193
|
-
|
194
|
-
name ||= "SQL"
|
195
|
-
@instrumenter.instrument("sql.active_record",
|
196
|
-
:sql => sql, :name => name, :connection_id => object_id) do
|
197
|
-
yield
|
198
|
-
end
|
199
|
-
rescue Exception => e
|
200
|
-
message = "#{e.class.name}: #{e.message}: #{sql}"
|
201
|
-
@logger.debug message if @logger
|
202
|
-
raise translate_exception(e, message)
|
203
|
-
end
|
417
|
+
protected
|
204
418
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
419
|
+
def log(sql, name = "SQL", binds = [])
|
420
|
+
@instrumenter.instrument(
|
421
|
+
"sql.active_record",
|
422
|
+
:sql => sql,
|
423
|
+
:name => name,
|
424
|
+
:connection_id => object_id,
|
425
|
+
:binds => binds) { yield }
|
426
|
+
rescue => e
|
427
|
+
message = "#{e.class.name}: #{e.message}: #{sql}"
|
428
|
+
@logger.error message if @logger
|
429
|
+
exception = translate_exception(e, message)
|
430
|
+
exception.set_backtrace e.backtrace
|
431
|
+
raise exception
|
432
|
+
end
|
209
433
|
|
434
|
+
def translate_exception(exception, message)
|
435
|
+
# override in derived class
|
436
|
+
ActiveRecord::StatementInvalid.new(message, exception)
|
437
|
+
end
|
210
438
|
end
|
211
439
|
end
|
212
440
|
end
|