activerecord 4.2.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.

Files changed (221) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1372 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +218 -0
  5. data/examples/performance.rb +184 -0
  6. data/examples/simple.rb +14 -0
  7. data/lib/active_record.rb +173 -0
  8. data/lib/active_record/aggregations.rb +266 -0
  9. data/lib/active_record/association_relation.rb +22 -0
  10. data/lib/active_record/associations.rb +1724 -0
  11. data/lib/active_record/associations/alias_tracker.rb +87 -0
  12. data/lib/active_record/associations/association.rb +253 -0
  13. data/lib/active_record/associations/association_scope.rb +194 -0
  14. data/lib/active_record/associations/belongs_to_association.rb +111 -0
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +40 -0
  16. data/lib/active_record/associations/builder/association.rb +149 -0
  17. data/lib/active_record/associations/builder/belongs_to.rb +116 -0
  18. data/lib/active_record/associations/builder/collection_association.rb +91 -0
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +124 -0
  20. data/lib/active_record/associations/builder/has_many.rb +15 -0
  21. data/lib/active_record/associations/builder/has_one.rb +23 -0
  22. data/lib/active_record/associations/builder/singular_association.rb +38 -0
  23. data/lib/active_record/associations/collection_association.rb +634 -0
  24. data/lib/active_record/associations/collection_proxy.rb +1027 -0
  25. data/lib/active_record/associations/has_many_association.rb +184 -0
  26. data/lib/active_record/associations/has_many_through_association.rb +238 -0
  27. data/lib/active_record/associations/has_one_association.rb +105 -0
  28. data/lib/active_record/associations/has_one_through_association.rb +36 -0
  29. data/lib/active_record/associations/join_dependency.rb +282 -0
  30. data/lib/active_record/associations/join_dependency/join_association.rb +122 -0
  31. data/lib/active_record/associations/join_dependency/join_base.rb +22 -0
  32. data/lib/active_record/associations/join_dependency/join_part.rb +71 -0
  33. data/lib/active_record/associations/preloader.rb +203 -0
  34. data/lib/active_record/associations/preloader/association.rb +162 -0
  35. data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
  36. data/lib/active_record/associations/preloader/collection_association.rb +24 -0
  37. data/lib/active_record/associations/preloader/has_many.rb +17 -0
  38. data/lib/active_record/associations/preloader/has_many_through.rb +19 -0
  39. data/lib/active_record/associations/preloader/has_one.rb +23 -0
  40. data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
  41. data/lib/active_record/associations/preloader/singular_association.rb +21 -0
  42. data/lib/active_record/associations/preloader/through_association.rb +96 -0
  43. data/lib/active_record/associations/singular_association.rb +86 -0
  44. data/lib/active_record/associations/through_association.rb +96 -0
  45. data/lib/active_record/attribute.rb +149 -0
  46. data/lib/active_record/attribute_assignment.rb +212 -0
  47. data/lib/active_record/attribute_decorators.rb +66 -0
  48. data/lib/active_record/attribute_methods.rb +439 -0
  49. data/lib/active_record/attribute_methods/before_type_cast.rb +71 -0
  50. data/lib/active_record/attribute_methods/dirty.rb +181 -0
  51. data/lib/active_record/attribute_methods/primary_key.rb +128 -0
  52. data/lib/active_record/attribute_methods/query.rb +40 -0
  53. data/lib/active_record/attribute_methods/read.rb +103 -0
  54. data/lib/active_record/attribute_methods/serialization.rb +70 -0
  55. data/lib/active_record/attribute_methods/time_zone_conversion.rb +65 -0
  56. data/lib/active_record/attribute_methods/write.rb +83 -0
  57. data/lib/active_record/attribute_set.rb +77 -0
  58. data/lib/active_record/attribute_set/builder.rb +86 -0
  59. data/lib/active_record/attributes.rb +139 -0
  60. data/lib/active_record/autosave_association.rb +439 -0
  61. data/lib/active_record/base.rb +317 -0
  62. data/lib/active_record/callbacks.rb +313 -0
  63. data/lib/active_record/coders/json.rb +13 -0
  64. data/lib/active_record/coders/yaml_column.rb +38 -0
  65. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +659 -0
  66. data/lib/active_record/connection_adapters/abstract/database_limits.rb +67 -0
  67. data/lib/active_record/connection_adapters/abstract/database_statements.rb +373 -0
  68. data/lib/active_record/connection_adapters/abstract/query_cache.rb +95 -0
  69. data/lib/active_record/connection_adapters/abstract/quoting.rb +133 -0
  70. data/lib/active_record/connection_adapters/abstract/savepoints.rb +21 -0
  71. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +125 -0
  72. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +574 -0
  73. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +50 -0
  74. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +991 -0
  75. data/lib/active_record/connection_adapters/abstract/transaction.rb +219 -0
  76. data/lib/active_record/connection_adapters/abstract_adapter.rb +487 -0
  77. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +883 -0
  78. data/lib/active_record/connection_adapters/column.rb +82 -0
  79. data/lib/active_record/connection_adapters/connection_specification.rb +275 -0
  80. data/lib/active_record/connection_adapters/mysql2_adapter.rb +282 -0
  81. data/lib/active_record/connection_adapters/mysql_adapter.rb +491 -0
  82. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +93 -0
  83. data/lib/active_record/connection_adapters/postgresql/column.rb +20 -0
  84. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +232 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid.rb +36 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +99 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +14 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +46 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +11 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +27 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +17 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +21 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +13 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +11 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +35 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +43 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +79 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +15 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +11 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +97 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +21 -0
  109. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
  110. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
  111. data/lib/active_record/connection_adapters/postgresql/quoting.rb +108 -0
  112. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +152 -0
  114. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +588 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +754 -0
  117. data/lib/active_record/connection_adapters/schema_cache.rb +94 -0
  118. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +628 -0
  119. data/lib/active_record/connection_adapters/statement_pool.rb +40 -0
  120. data/lib/active_record/connection_handling.rb +132 -0
  121. data/lib/active_record/core.rb +566 -0
  122. data/lib/active_record/counter_cache.rb +175 -0
  123. data/lib/active_record/dynamic_matchers.rb +140 -0
  124. data/lib/active_record/enum.rb +198 -0
  125. data/lib/active_record/errors.rb +252 -0
  126. data/lib/active_record/explain.rb +38 -0
  127. data/lib/active_record/explain_registry.rb +30 -0
  128. data/lib/active_record/explain_subscriber.rb +29 -0
  129. data/lib/active_record/fixture_set/file.rb +56 -0
  130. data/lib/active_record/fixtures.rb +1007 -0
  131. data/lib/active_record/gem_version.rb +15 -0
  132. data/lib/active_record/inheritance.rb +247 -0
  133. data/lib/active_record/integration.rb +113 -0
  134. data/lib/active_record/locale/en.yml +47 -0
  135. data/lib/active_record/locking/optimistic.rb +204 -0
  136. data/lib/active_record/locking/pessimistic.rb +77 -0
  137. data/lib/active_record/log_subscriber.rb +75 -0
  138. data/lib/active_record/migration.rb +1051 -0
  139. data/lib/active_record/migration/command_recorder.rb +197 -0
  140. data/lib/active_record/migration/join_table.rb +15 -0
  141. data/lib/active_record/model_schema.rb +340 -0
  142. data/lib/active_record/nested_attributes.rb +548 -0
  143. data/lib/active_record/no_touching.rb +52 -0
  144. data/lib/active_record/null_relation.rb +81 -0
  145. data/lib/active_record/persistence.rb +532 -0
  146. data/lib/active_record/query_cache.rb +56 -0
  147. data/lib/active_record/querying.rb +68 -0
  148. data/lib/active_record/railtie.rb +162 -0
  149. data/lib/active_record/railties/console_sandbox.rb +5 -0
  150. data/lib/active_record/railties/controller_runtime.rb +50 -0
  151. data/lib/active_record/railties/databases.rake +391 -0
  152. data/lib/active_record/railties/jdbcmysql_error.rb +16 -0
  153. data/lib/active_record/readonly_attributes.rb +23 -0
  154. data/lib/active_record/reflection.rb +881 -0
  155. data/lib/active_record/relation.rb +681 -0
  156. data/lib/active_record/relation/batches.rb +138 -0
  157. data/lib/active_record/relation/calculations.rb +403 -0
  158. data/lib/active_record/relation/delegation.rb +140 -0
  159. data/lib/active_record/relation/finder_methods.rb +528 -0
  160. data/lib/active_record/relation/merger.rb +170 -0
  161. data/lib/active_record/relation/predicate_builder.rb +126 -0
  162. data/lib/active_record/relation/predicate_builder/array_handler.rb +47 -0
  163. data/lib/active_record/relation/predicate_builder/relation_handler.rb +13 -0
  164. data/lib/active_record/relation/query_methods.rb +1176 -0
  165. data/lib/active_record/relation/spawn_methods.rb +75 -0
  166. data/lib/active_record/result.rb +131 -0
  167. data/lib/active_record/runtime_registry.rb +22 -0
  168. data/lib/active_record/sanitization.rb +191 -0
  169. data/lib/active_record/schema.rb +64 -0
  170. data/lib/active_record/schema_dumper.rb +251 -0
  171. data/lib/active_record/schema_migration.rb +56 -0
  172. data/lib/active_record/scoping.rb +87 -0
  173. data/lib/active_record/scoping/default.rb +134 -0
  174. data/lib/active_record/scoping/named.rb +164 -0
  175. data/lib/active_record/serialization.rb +22 -0
  176. data/lib/active_record/serializers/xml_serializer.rb +193 -0
  177. data/lib/active_record/statement_cache.rb +111 -0
  178. data/lib/active_record/store.rb +205 -0
  179. data/lib/active_record/tasks/database_tasks.rb +296 -0
  180. data/lib/active_record/tasks/mysql_database_tasks.rb +145 -0
  181. data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
  182. data/lib/active_record/tasks/sqlite_database_tasks.rb +55 -0
  183. data/lib/active_record/timestamp.rb +121 -0
  184. data/lib/active_record/transactions.rb +417 -0
  185. data/lib/active_record/translation.rb +22 -0
  186. data/lib/active_record/type.rb +23 -0
  187. data/lib/active_record/type/big_integer.rb +13 -0
  188. data/lib/active_record/type/binary.rb +50 -0
  189. data/lib/active_record/type/boolean.rb +30 -0
  190. data/lib/active_record/type/date.rb +46 -0
  191. data/lib/active_record/type/date_time.rb +43 -0
  192. data/lib/active_record/type/decimal.rb +40 -0
  193. data/lib/active_record/type/decimal_without_scale.rb +11 -0
  194. data/lib/active_record/type/decorator.rb +14 -0
  195. data/lib/active_record/type/float.rb +19 -0
  196. data/lib/active_record/type/hash_lookup_type_map.rb +17 -0
  197. data/lib/active_record/type/integer.rb +55 -0
  198. data/lib/active_record/type/mutable.rb +16 -0
  199. data/lib/active_record/type/numeric.rb +36 -0
  200. data/lib/active_record/type/serialized.rb +56 -0
  201. data/lib/active_record/type/string.rb +36 -0
  202. data/lib/active_record/type/text.rb +11 -0
  203. data/lib/active_record/type/time.rb +26 -0
  204. data/lib/active_record/type/time_value.rb +38 -0
  205. data/lib/active_record/type/type_map.rb +64 -0
  206. data/lib/active_record/type/unsigned_integer.rb +15 -0
  207. data/lib/active_record/type/value.rb +101 -0
  208. data/lib/active_record/validations.rb +90 -0
  209. data/lib/active_record/validations/associated.rb +51 -0
  210. data/lib/active_record/validations/presence.rb +67 -0
  211. data/lib/active_record/validations/uniqueness.rb +229 -0
  212. data/lib/active_record/version.rb +8 -0
  213. data/lib/rails/generators/active_record.rb +17 -0
  214. data/lib/rails/generators/active_record/migration.rb +18 -0
  215. data/lib/rails/generators/active_record/migration/migration_generator.rb +70 -0
  216. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +22 -0
  217. data/lib/rails/generators/active_record/migration/templates/migration.rb +45 -0
  218. data/lib/rails/generators/active_record/model/model_generator.rb +52 -0
  219. data/lib/rails/generators/active_record/model/templates/model.rb +10 -0
  220. data/lib/rails/generators/active_record/model/templates/module.rb +7 -0
  221. metadata +309 -0
@@ -0,0 +1,219 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class TransactionState
4
+ attr_reader :parent
5
+
6
+ VALID_STATES = Set.new([:committed, :rolledback, nil])
7
+
8
+ def initialize(state = nil)
9
+ @state = state
10
+ @parent = nil
11
+ end
12
+
13
+ def finalized?
14
+ @state
15
+ end
16
+
17
+ def committed?
18
+ @state == :committed
19
+ end
20
+
21
+ def rolledback?
22
+ @state == :rolledback
23
+ end
24
+
25
+ def completed?
26
+ committed? || rolledback?
27
+ end
28
+
29
+ def set_state(state)
30
+ if !VALID_STATES.include?(state)
31
+ raise ArgumentError, "Invalid transaction state: #{state}"
32
+ end
33
+ @state = state
34
+ end
35
+ end
36
+
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
43
+ end
44
+
45
+ class Transaction #:nodoc:
46
+
47
+ attr_reader :connection, :state, :records, :savepoint_name
48
+ attr_writer :joinable
49
+
50
+ def initialize(connection, options)
51
+ @connection = connection
52
+ @state = TransactionState.new
53
+ @records = []
54
+ @joinable = options.fetch(:joinable, true)
55
+ end
56
+
57
+ def add_record(record)
58
+ if record.has_transactional_callbacks?
59
+ records << record
60
+ else
61
+ record.set_transaction_state(@state)
62
+ end
63
+ end
64
+
65
+ def rollback
66
+ @state.set_state(:rolledback)
67
+ end
68
+
69
+ def rollback_records
70
+ ite = records.uniq
71
+ while record = ite.shift
72
+ begin
73
+ record.rolledback! full_rollback?
74
+ rescue => e
75
+ raise if ActiveRecord::Base.raise_in_transactional_callbacks
76
+ record.logger.error(e) if record.respond_to?(:logger) && record.logger
77
+ end
78
+ end
79
+ ensure
80
+ ite.each do |i|
81
+ i.rolledback!(full_rollback?, false)
82
+ end
83
+ end
84
+
85
+ def commit
86
+ @state.set_state(:committed)
87
+ end
88
+
89
+ def commit_records
90
+ ite = records.uniq
91
+ while record = ite.shift
92
+ begin
93
+ record.committed!
94
+ rescue => e
95
+ raise if ActiveRecord::Base.raise_in_transactional_callbacks
96
+ record.logger.error(e) if record.respond_to?(:logger) && record.logger
97
+ end
98
+ end
99
+ ensure
100
+ ite.each do |i|
101
+ i.committed!(false)
102
+ end
103
+ end
104
+
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)
119
+ end
120
+
121
+ def rollback
122
+ connection.rollback_to_savepoint(savepoint_name)
123
+ super
124
+ rollback_records
125
+ end
126
+
127
+ def commit
128
+ connection.release_savepoint(savepoint_name)
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
136
+
137
+ class RealTransaction < Transaction
138
+
139
+ def initialize(connection, options)
140
+ super
141
+ if options[:isolation]
142
+ connection.begin_isolated_db_transaction(options[:isolation])
143
+ else
144
+ connection.begin_db_transaction
145
+ end
146
+ end
147
+
148
+ def rollback
149
+ connection.rollback_db_transaction
150
+ super
151
+ rollback_records
152
+ end
153
+
154
+ def commit
155
+ connection.commit_db_transaction
156
+ super
157
+ commit_records
158
+ end
159
+ end
160
+
161
+ class TransactionManager #:nodoc:
162
+ def initialize(connection)
163
+ @stack = []
164
+ @connection = connection
165
+ end
166
+
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
176
+ end
177
+
178
+ def commit_transaction
179
+ @stack.pop.commit
180
+ end
181
+
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
+ unless error
194
+ if Thread.current.status == 'aborting'
195
+ rollback_transaction
196
+ else
197
+ begin
198
+ commit_transaction
199
+ rescue Exception
200
+ transaction.rollback unless transaction.state.completed?
201
+ raise
202
+ end
203
+ end
204
+ end
205
+ end
206
+
207
+ def open_transactions
208
+ @stack.size
209
+ end
210
+
211
+ def current_transaction
212
+ @stack.last || NULL_TRANSACTION
213
+ end
214
+
215
+ private
216
+ NULL_TRANSACTION = NullTransaction.new
217
+ end
218
+ end
219
+ end
@@ -0,0 +1,487 @@
1
+ require 'date'
2
+ require 'bigdecimal'
3
+ require 'bigdecimal/util'
4
+ require 'active_record/type'
5
+ require 'active_support/core_ext/benchmark'
6
+ require 'active_record/connection_adapters/schema_cache'
7
+ require 'active_record/connection_adapters/abstract/schema_dumper'
8
+ require 'active_record/connection_adapters/abstract/schema_creation'
9
+ require 'monitor'
10
+ require 'arel/collectors/bind'
11
+ require 'arel/collectors/sql_string'
12
+
13
+ module ActiveRecord
14
+ module ConnectionAdapters # :nodoc:
15
+ extend ActiveSupport::Autoload
16
+
17
+ autoload :Column
18
+ autoload :ConnectionSpecification
19
+
20
+ autoload_at 'active_record/connection_adapters/abstract/schema_definitions' do
21
+ autoload :IndexDefinition
22
+ autoload :ColumnDefinition
23
+ autoload :ChangeColumnDefinition
24
+ autoload :TableDefinition
25
+ autoload :Table
26
+ autoload :AlterTable
27
+ autoload :TimestampDefaultDeprecation
28
+ end
29
+
30
+ autoload_at 'active_record/connection_adapters/abstract/connection_pool' do
31
+ autoload :ConnectionHandler
32
+ autoload :ConnectionManagement
33
+ end
34
+
35
+ autoload_under 'abstract' do
36
+ autoload :SchemaStatements
37
+ autoload :DatabaseStatements
38
+ autoload :DatabaseLimits
39
+ autoload :Quoting
40
+ autoload :ConnectionPool
41
+ autoload :QueryCache
42
+ autoload :Savepoints
43
+ end
44
+
45
+ autoload_at 'active_record/connection_adapters/abstract/transaction' do
46
+ autoload :TransactionManager
47
+ autoload :NullTransaction
48
+ autoload :RealTransaction
49
+ autoload :SavepointTransaction
50
+ autoload :TransactionState
51
+ end
52
+
53
+ # Active Record supports multiple database systems. AbstractAdapter and
54
+ # related classes form the abstraction layer which makes this possible.
55
+ # An AbstractAdapter represents a connection to a database, and provides an
56
+ # abstract interface for database-specific functionality such as establishing
57
+ # a connection, escaping values, building the right SQL fragments for ':offset'
58
+ # and ':limit' options, etc.
59
+ #
60
+ # All the concrete database adapters follow the interface laid down in this class.
61
+ # ActiveRecord::Base.connection returns an AbstractAdapter object, which
62
+ # you can use.
63
+ #
64
+ # Most of the methods in the adapter are useful during migrations. Most
65
+ # notably, the instance methods provided by SchemaStatement are very useful.
66
+ class AbstractAdapter
67
+ ADAPTER_NAME = 'Abstract'.freeze
68
+ include Quoting, DatabaseStatements, SchemaStatements
69
+ include DatabaseLimits
70
+ include QueryCache
71
+ include ActiveSupport::Callbacks
72
+ include MonitorMixin
73
+ include ColumnDumper
74
+
75
+ SIMPLE_INT = /\A\d+\z/
76
+
77
+ define_callbacks :checkout, :checkin
78
+
79
+ attr_accessor :visitor, :pool
80
+ attr_reader :schema_cache, :owner, :logger
81
+ alias :in_use? :owner
82
+
83
+ def self.type_cast_config_to_integer(config)
84
+ if config =~ SIMPLE_INT
85
+ config.to_i
86
+ else
87
+ config
88
+ end
89
+ end
90
+
91
+ def self.type_cast_config_to_boolean(config)
92
+ if config == "false"
93
+ false
94
+ else
95
+ config
96
+ end
97
+ end
98
+
99
+ attr_reader :prepared_statements
100
+
101
+ def initialize(connection, logger = nil, pool = nil) #:nodoc:
102
+ super()
103
+
104
+ @connection = connection
105
+ @owner = nil
106
+ @instrumenter = ActiveSupport::Notifications.instrumenter
107
+ @logger = logger
108
+ @pool = pool
109
+ @schema_cache = SchemaCache.new self
110
+ @visitor = nil
111
+ @prepared_statements = false
112
+ end
113
+
114
+ class BindCollector < Arel::Collectors::Bind
115
+ def compile(bvs, conn)
116
+ super(bvs.map { |bv| conn.quote(*bv.reverse) })
117
+ end
118
+ end
119
+
120
+ class SQLString < Arel::Collectors::SQLString
121
+ def compile(bvs, conn)
122
+ super(bvs)
123
+ end
124
+ end
125
+
126
+ def collector
127
+ if prepared_statements
128
+ SQLString.new
129
+ else
130
+ BindCollector.new
131
+ end
132
+ end
133
+
134
+ def valid_type?(type)
135
+ true
136
+ end
137
+
138
+ def schema_creation
139
+ SchemaCreation.new self
140
+ end
141
+
142
+ def lease
143
+ synchronize do
144
+ unless in_use?
145
+ @owner = Thread.current
146
+ end
147
+ end
148
+ end
149
+
150
+ def schema_cache=(cache)
151
+ cache.connection = self
152
+ @schema_cache = cache
153
+ end
154
+
155
+ def expire
156
+ @owner = nil
157
+ end
158
+
159
+ def unprepared_statement
160
+ old_prepared_statements, @prepared_statements = @prepared_statements, false
161
+ yield
162
+ ensure
163
+ @prepared_statements = old_prepared_statements
164
+ end
165
+
166
+ # Returns the human-readable name of the adapter. Use mixed case - one
167
+ # can always use downcase if needed.
168
+ def adapter_name
169
+ self.class::ADAPTER_NAME
170
+ end
171
+
172
+ # Does this adapter support migrations?
173
+ def supports_migrations?
174
+ false
175
+ end
176
+
177
+ # Can this adapter determine the primary key for tables not attached
178
+ # to an Active Record class, such as join tables?
179
+ def supports_primary_key?
180
+ false
181
+ end
182
+
183
+ # Does this adapter support DDL rollbacks in transactions? That is, would
184
+ # CREATE TABLE or ALTER TABLE get rolled back by a transaction?
185
+ def supports_ddl_transactions?
186
+ false
187
+ end
188
+
189
+ def supports_bulk_alter?
190
+ false
191
+ end
192
+
193
+ # Does this adapter support savepoints?
194
+ def supports_savepoints?
195
+ false
196
+ end
197
+
198
+ # Should primary key values be selected from their corresponding
199
+ # sequence before the insert statement? If true, next_sequence_value
200
+ # is called before each insert to set the record's primary key.
201
+ def prefetch_primary_key?(table_name = nil)
202
+ false
203
+ end
204
+
205
+ # Does this adapter support index sort order?
206
+ def supports_index_sort_order?
207
+ false
208
+ end
209
+
210
+ # Does this adapter support partial indices?
211
+ def supports_partial_index?
212
+ false
213
+ end
214
+
215
+ # Does this adapter support explain?
216
+ def supports_explain?
217
+ false
218
+ end
219
+
220
+ # Does this adapter support setting the isolation level for a transaction?
221
+ def supports_transaction_isolation?
222
+ false
223
+ end
224
+
225
+ # Does this adapter support database extensions?
226
+ def supports_extensions?
227
+ false
228
+ end
229
+
230
+ # Does this adapter support creating indexes in the same statement as
231
+ # creating the table?
232
+ def supports_indexes_in_create?
233
+ false
234
+ end
235
+
236
+ # Does this adapter support creating foreign key constraints?
237
+ def supports_foreign_keys?
238
+ false
239
+ end
240
+
241
+ # Does this adapter support views?
242
+ def supports_views?
243
+ false
244
+ end
245
+
246
+ # This is meant to be implemented by the adapters that support extensions
247
+ def disable_extension(name)
248
+ end
249
+
250
+ # This is meant to be implemented by the adapters that support extensions
251
+ def enable_extension(name)
252
+ end
253
+
254
+ # A list of extensions, to be filled in by adapters that support them.
255
+ def extensions
256
+ []
257
+ end
258
+
259
+ # A list of index algorithms, to be filled by adapters that support them.
260
+ def index_algorithms
261
+ {}
262
+ end
263
+
264
+ # QUOTING ==================================================
265
+
266
+ # Returns a bind substitution value given a bind +column+
267
+ # NOTE: The column param is currently being used by the sqlserver-adapter
268
+ def substitute_at(column, _unused = 0)
269
+ Arel::Nodes::BindParam.new
270
+ end
271
+
272
+ # REFERENTIAL INTEGRITY ====================================
273
+
274
+ # Override to turn off referential integrity while executing <tt>&block</tt>.
275
+ def disable_referential_integrity
276
+ yield
277
+ end
278
+
279
+ # CONNECTION MANAGEMENT ====================================
280
+
281
+ # Checks whether the connection to the database is still active. This includes
282
+ # checking whether the database is actually capable of responding, i.e. whether
283
+ # the connection isn't stale.
284
+ def active?
285
+ end
286
+
287
+ # Disconnects from the database if already connected, and establishes a
288
+ # new connection with the database. Implementors should call super if they
289
+ # override the default implementation.
290
+ def reconnect!
291
+ clear_cache!
292
+ reset_transaction
293
+ end
294
+
295
+ # Disconnects from the database if already connected. Otherwise, this
296
+ # method does nothing.
297
+ def disconnect!
298
+ clear_cache!
299
+ reset_transaction
300
+ end
301
+
302
+ # Reset the state of this connection, directing the DBMS to clear
303
+ # transactions and other connection-related server-side state. Usually a
304
+ # database-dependent operation.
305
+ #
306
+ # The default implementation does nothing; the implementation should be
307
+ # overridden by concrete adapters.
308
+ def reset!
309
+ # this should be overridden by concrete adapters
310
+ end
311
+
312
+ ###
313
+ # Clear any caching the database adapter may be doing, for example
314
+ # clearing the prepared statement cache. This is database specific.
315
+ def clear_cache!
316
+ # this should be overridden by concrete adapters
317
+ end
318
+
319
+ # Returns true if its required to reload the connection between requests for development mode.
320
+ def requires_reloading?
321
+ false
322
+ end
323
+
324
+ # Checks whether the connection to the database is still active (i.e. not stale).
325
+ # This is done under the hood by calling <tt>active?</tt>. If the connection
326
+ # is no longer active, then this method will reconnect to the database.
327
+ def verify!(*ignored)
328
+ reconnect! unless active?
329
+ end
330
+
331
+ # Provides access to the underlying database driver for this adapter. For
332
+ # example, this method returns a Mysql object in case of MysqlAdapter,
333
+ # and a PGconn object in case of PostgreSQLAdapter.
334
+ #
335
+ # This is useful for when you need to call a proprietary method such as
336
+ # PostgreSQL's lo_* methods.
337
+ def raw_connection
338
+ @connection
339
+ end
340
+
341
+ def create_savepoint(name = nil)
342
+ end
343
+
344
+ def rollback_to_savepoint(name = nil)
345
+ end
346
+
347
+ def release_savepoint(name = nil)
348
+ end
349
+
350
+ def case_sensitive_modifier(node, table_attribute)
351
+ node
352
+ end
353
+
354
+ def case_sensitive_comparison(table, attribute, column, value)
355
+ table_attr = table[attribute]
356
+ value = case_sensitive_modifier(value, table_attr) unless value.nil?
357
+ table_attr.eq(value)
358
+ end
359
+
360
+ def case_insensitive_comparison(table, attribute, column, value)
361
+ table[attribute].lower.eq(table.lower(value))
362
+ end
363
+
364
+ def current_savepoint_name
365
+ current_transaction.savepoint_name
366
+ end
367
+
368
+ # Check the connection back in to the connection pool
369
+ def close
370
+ pool.checkin self
371
+ end
372
+
373
+ def type_map # :nodoc:
374
+ @type_map ||= Type::TypeMap.new.tap do |mapping|
375
+ initialize_type_map(mapping)
376
+ end
377
+ end
378
+
379
+ def new_column(name, default, cast_type, sql_type = nil, null = true)
380
+ Column.new(name, default, cast_type, sql_type, null)
381
+ end
382
+
383
+ def lookup_cast_type(sql_type) # :nodoc:
384
+ type_map.lookup(sql_type)
385
+ end
386
+
387
+ def column_name_for_operation(operation, node) # :nodoc:
388
+ node.to_sql
389
+ end
390
+
391
+ protected
392
+
393
+ def initialize_type_map(m) # :nodoc:
394
+ register_class_with_limit m, %r(boolean)i, Type::Boolean
395
+ register_class_with_limit m, %r(char)i, Type::String
396
+ register_class_with_limit m, %r(binary)i, Type::Binary
397
+ register_class_with_limit m, %r(text)i, Type::Text
398
+ register_class_with_limit m, %r(date)i, Type::Date
399
+ register_class_with_limit m, %r(time)i, Type::Time
400
+ register_class_with_limit m, %r(datetime)i, Type::DateTime
401
+ register_class_with_limit m, %r(float)i, Type::Float
402
+ register_class_with_limit m, %r(int)i, Type::Integer
403
+
404
+ m.alias_type %r(blob)i, 'binary'
405
+ m.alias_type %r(clob)i, 'text'
406
+ m.alias_type %r(timestamp)i, 'datetime'
407
+ m.alias_type %r(numeric)i, 'decimal'
408
+ m.alias_type %r(number)i, 'decimal'
409
+ m.alias_type %r(double)i, 'float'
410
+
411
+ m.register_type(%r(decimal)i) do |sql_type|
412
+ scale = extract_scale(sql_type)
413
+ precision = extract_precision(sql_type)
414
+
415
+ if scale == 0
416
+ # FIXME: Remove this class as well
417
+ Type::DecimalWithoutScale.new(precision: precision)
418
+ else
419
+ Type::Decimal.new(precision: precision, scale: scale)
420
+ end
421
+ end
422
+ end
423
+
424
+ def reload_type_map # :nodoc:
425
+ type_map.clear
426
+ initialize_type_map(type_map)
427
+ end
428
+
429
+ def register_class_with_limit(mapping, key, klass) # :nodoc:
430
+ mapping.register_type(key) do |*args|
431
+ limit = extract_limit(args.last)
432
+ klass.new(limit: limit)
433
+ end
434
+ end
435
+
436
+ def extract_scale(sql_type) # :nodoc:
437
+ case sql_type
438
+ when /\((\d+)\)/ then 0
439
+ when /\((\d+)(,(\d+))\)/ then $3.to_i
440
+ end
441
+ end
442
+
443
+ def extract_precision(sql_type) # :nodoc:
444
+ $1.to_i if sql_type =~ /\((\d+)(,\d+)?\)/
445
+ end
446
+
447
+ def extract_limit(sql_type) # :nodoc:
448
+ $1.to_i if sql_type =~ /\((.*)\)/
449
+ end
450
+
451
+ def translate_exception_class(e, sql)
452
+ message = "#{e.class.name}: #{e.message}: #{sql}"
453
+ @logger.error message if @logger
454
+ exception = translate_exception(e, message)
455
+ exception.set_backtrace e.backtrace
456
+ exception
457
+ end
458
+
459
+ def log(sql, name = "SQL", binds = [], statement_name = nil)
460
+ @instrumenter.instrument(
461
+ "sql.active_record",
462
+ :sql => sql,
463
+ :name => name,
464
+ :connection_id => object_id,
465
+ :statement_name => statement_name,
466
+ :binds => binds) { yield }
467
+ rescue => e
468
+ raise translate_exception_class(e, sql)
469
+ end
470
+
471
+ def translate_exception(exception, message)
472
+ # override in derived class
473
+ ActiveRecord::StatementInvalid.new(message, exception)
474
+ end
475
+
476
+ def without_prepared_statement?(binds)
477
+ !prepared_statements || binds.empty?
478
+ end
479
+
480
+ def column_for(table_name, column_name) # :nodoc:
481
+ column_name = column_name.to_s
482
+ columns(table_name).detect { |c| c.name == column_name } ||
483
+ raise(ActiveRecordError, "No such column: #{table_name}.#{column_name}")
484
+ end
485
+ end
486
+ end
487
+ end