activerecord 5.2.3

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 (244) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +937 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +217 -0
  5. data/examples/performance.rb +185 -0
  6. data/examples/simple.rb +15 -0
  7. data/lib/active_record.rb +188 -0
  8. data/lib/active_record/aggregations.rb +283 -0
  9. data/lib/active_record/association_relation.rb +40 -0
  10. data/lib/active_record/associations.rb +1860 -0
  11. data/lib/active_record/associations/alias_tracker.rb +81 -0
  12. data/lib/active_record/associations/association.rb +299 -0
  13. data/lib/active_record/associations/association_scope.rb +168 -0
  14. data/lib/active_record/associations/belongs_to_association.rb +130 -0
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +40 -0
  16. data/lib/active_record/associations/builder/association.rb +140 -0
  17. data/lib/active_record/associations/builder/belongs_to.rb +163 -0
  18. data/lib/active_record/associations/builder/collection_association.rb +82 -0
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +135 -0
  20. data/lib/active_record/associations/builder/has_many.rb +17 -0
  21. data/lib/active_record/associations/builder/has_one.rb +30 -0
  22. data/lib/active_record/associations/builder/singular_association.rb +42 -0
  23. data/lib/active_record/associations/collection_association.rb +513 -0
  24. data/lib/active_record/associations/collection_proxy.rb +1131 -0
  25. data/lib/active_record/associations/foreign_association.rb +13 -0
  26. data/lib/active_record/associations/has_many_association.rb +144 -0
  27. data/lib/active_record/associations/has_many_through_association.rb +227 -0
  28. data/lib/active_record/associations/has_one_association.rb +120 -0
  29. data/lib/active_record/associations/has_one_through_association.rb +45 -0
  30. data/lib/active_record/associations/join_dependency.rb +262 -0
  31. data/lib/active_record/associations/join_dependency/join_association.rb +60 -0
  32. data/lib/active_record/associations/join_dependency/join_base.rb +23 -0
  33. data/lib/active_record/associations/join_dependency/join_part.rb +71 -0
  34. data/lib/active_record/associations/preloader.rb +193 -0
  35. data/lib/active_record/associations/preloader/association.rb +131 -0
  36. data/lib/active_record/associations/preloader/through_association.rb +107 -0
  37. data/lib/active_record/associations/singular_association.rb +73 -0
  38. data/lib/active_record/associations/through_association.rb +121 -0
  39. data/lib/active_record/attribute_assignment.rb +88 -0
  40. data/lib/active_record/attribute_decorators.rb +90 -0
  41. data/lib/active_record/attribute_methods.rb +492 -0
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +78 -0
  43. data/lib/active_record/attribute_methods/dirty.rb +150 -0
  44. data/lib/active_record/attribute_methods/primary_key.rb +143 -0
  45. data/lib/active_record/attribute_methods/query.rb +42 -0
  46. data/lib/active_record/attribute_methods/read.rb +85 -0
  47. data/lib/active_record/attribute_methods/serialization.rb +90 -0
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +91 -0
  49. data/lib/active_record/attribute_methods/write.rb +68 -0
  50. data/lib/active_record/attributes.rb +266 -0
  51. data/lib/active_record/autosave_association.rb +498 -0
  52. data/lib/active_record/base.rb +329 -0
  53. data/lib/active_record/callbacks.rb +353 -0
  54. data/lib/active_record/coders/json.rb +15 -0
  55. data/lib/active_record/coders/yaml_column.rb +50 -0
  56. data/lib/active_record/collection_cache_key.rb +53 -0
  57. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +1068 -0
  58. data/lib/active_record/connection_adapters/abstract/database_limits.rb +72 -0
  59. data/lib/active_record/connection_adapters/abstract/database_statements.rb +540 -0
  60. data/lib/active_record/connection_adapters/abstract/query_cache.rb +145 -0
  61. data/lib/active_record/connection_adapters/abstract/quoting.rb +200 -0
  62. data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +146 -0
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +685 -0
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +95 -0
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1396 -0
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +283 -0
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +628 -0
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +887 -0
  70. data/lib/active_record/connection_adapters/column.rb +91 -0
  71. data/lib/active_record/connection_adapters/connection_specification.rb +287 -0
  72. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +33 -0
  73. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  74. data/lib/active_record/connection_adapters/mysql/database_statements.rb +140 -0
  75. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  76. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +73 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +87 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +80 -0
  80. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +148 -0
  81. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +35 -0
  82. data/lib/active_record/connection_adapters/mysql2_adapter.rb +129 -0
  83. data/lib/active_record/connection_adapters/postgresql/column.rb +44 -0
  84. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +163 -0
  85. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +92 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +56 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +23 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +41 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +111 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +23 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
  109. data/lib/active_record/connection_adapters/postgresql/quoting.rb +168 -0
  110. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +43 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +65 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +206 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  114. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +774 -0
  115. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +39 -0
  116. data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
  117. data/lib/active_record/connection_adapters/postgresql_adapter.rb +863 -0
  118. data/lib/active_record/connection_adapters/schema_cache.rb +118 -0
  119. data/lib/active_record/connection_adapters/sql_type_metadata.rb +34 -0
  120. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  121. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +67 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +106 -0
  126. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +573 -0
  127. data/lib/active_record/connection_adapters/statement_pool.rb +61 -0
  128. data/lib/active_record/connection_handling.rb +145 -0
  129. data/lib/active_record/core.rb +559 -0
  130. data/lib/active_record/counter_cache.rb +218 -0
  131. data/lib/active_record/define_callbacks.rb +22 -0
  132. data/lib/active_record/dynamic_matchers.rb +122 -0
  133. data/lib/active_record/enum.rb +244 -0
  134. data/lib/active_record/errors.rb +380 -0
  135. data/lib/active_record/explain.rb +50 -0
  136. data/lib/active_record/explain_registry.rb +32 -0
  137. data/lib/active_record/explain_subscriber.rb +34 -0
  138. data/lib/active_record/fixture_set/file.rb +82 -0
  139. data/lib/active_record/fixtures.rb +1065 -0
  140. data/lib/active_record/gem_version.rb +17 -0
  141. data/lib/active_record/inheritance.rb +283 -0
  142. data/lib/active_record/integration.rb +155 -0
  143. data/lib/active_record/internal_metadata.rb +45 -0
  144. data/lib/active_record/legacy_yaml_adapter.rb +48 -0
  145. data/lib/active_record/locale/en.yml +48 -0
  146. data/lib/active_record/locking/optimistic.rb +198 -0
  147. data/lib/active_record/locking/pessimistic.rb +89 -0
  148. data/lib/active_record/log_subscriber.rb +137 -0
  149. data/lib/active_record/migration.rb +1378 -0
  150. data/lib/active_record/migration/command_recorder.rb +240 -0
  151. data/lib/active_record/migration/compatibility.rb +217 -0
  152. data/lib/active_record/migration/join_table.rb +17 -0
  153. data/lib/active_record/model_schema.rb +521 -0
  154. data/lib/active_record/nested_attributes.rb +600 -0
  155. data/lib/active_record/no_touching.rb +58 -0
  156. data/lib/active_record/null_relation.rb +68 -0
  157. data/lib/active_record/persistence.rb +763 -0
  158. data/lib/active_record/query_cache.rb +45 -0
  159. data/lib/active_record/querying.rb +70 -0
  160. data/lib/active_record/railtie.rb +226 -0
  161. data/lib/active_record/railties/console_sandbox.rb +7 -0
  162. data/lib/active_record/railties/controller_runtime.rb +56 -0
  163. data/lib/active_record/railties/databases.rake +377 -0
  164. data/lib/active_record/readonly_attributes.rb +24 -0
  165. data/lib/active_record/reflection.rb +1044 -0
  166. data/lib/active_record/relation.rb +629 -0
  167. data/lib/active_record/relation/batches.rb +287 -0
  168. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  169. data/lib/active_record/relation/calculations.rb +417 -0
  170. data/lib/active_record/relation/delegation.rb +147 -0
  171. data/lib/active_record/relation/finder_methods.rb +565 -0
  172. data/lib/active_record/relation/from_clause.rb +26 -0
  173. data/lib/active_record/relation/merger.rb +193 -0
  174. data/lib/active_record/relation/predicate_builder.rb +152 -0
  175. data/lib/active_record/relation/predicate_builder/array_handler.rb +48 -0
  176. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  177. data/lib/active_record/relation/predicate_builder/base_handler.rb +19 -0
  178. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +20 -0
  179. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
  180. data/lib/active_record/relation/predicate_builder/range_handler.rb +42 -0
  181. data/lib/active_record/relation/predicate_builder/relation_handler.rb +19 -0
  182. data/lib/active_record/relation/query_attribute.rb +45 -0
  183. data/lib/active_record/relation/query_methods.rb +1231 -0
  184. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  185. data/lib/active_record/relation/spawn_methods.rb +77 -0
  186. data/lib/active_record/relation/where_clause.rb +186 -0
  187. data/lib/active_record/relation/where_clause_factory.rb +34 -0
  188. data/lib/active_record/result.rb +149 -0
  189. data/lib/active_record/runtime_registry.rb +24 -0
  190. data/lib/active_record/sanitization.rb +222 -0
  191. data/lib/active_record/schema.rb +70 -0
  192. data/lib/active_record/schema_dumper.rb +255 -0
  193. data/lib/active_record/schema_migration.rb +56 -0
  194. data/lib/active_record/scoping.rb +106 -0
  195. data/lib/active_record/scoping/default.rb +152 -0
  196. data/lib/active_record/scoping/named.rb +213 -0
  197. data/lib/active_record/secure_token.rb +40 -0
  198. data/lib/active_record/serialization.rb +22 -0
  199. data/lib/active_record/statement_cache.rb +121 -0
  200. data/lib/active_record/store.rb +211 -0
  201. data/lib/active_record/suppressor.rb +61 -0
  202. data/lib/active_record/table_metadata.rb +82 -0
  203. data/lib/active_record/tasks/database_tasks.rb +337 -0
  204. data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
  205. data/lib/active_record/tasks/postgresql_database_tasks.rb +143 -0
  206. data/lib/active_record/tasks/sqlite_database_tasks.rb +83 -0
  207. data/lib/active_record/timestamp.rb +153 -0
  208. data/lib/active_record/touch_later.rb +64 -0
  209. data/lib/active_record/transactions.rb +502 -0
  210. data/lib/active_record/translation.rb +24 -0
  211. data/lib/active_record/type.rb +79 -0
  212. data/lib/active_record/type/adapter_specific_registry.rb +136 -0
  213. data/lib/active_record/type/date.rb +9 -0
  214. data/lib/active_record/type/date_time.rb +9 -0
  215. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  216. data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
  217. data/lib/active_record/type/internal/timezone.rb +17 -0
  218. data/lib/active_record/type/json.rb +30 -0
  219. data/lib/active_record/type/serialized.rb +71 -0
  220. data/lib/active_record/type/text.rb +11 -0
  221. data/lib/active_record/type/time.rb +21 -0
  222. data/lib/active_record/type/type_map.rb +62 -0
  223. data/lib/active_record/type/unsigned_integer.rb +17 -0
  224. data/lib/active_record/type_caster.rb +9 -0
  225. data/lib/active_record/type_caster/connection.rb +33 -0
  226. data/lib/active_record/type_caster/map.rb +23 -0
  227. data/lib/active_record/validations.rb +93 -0
  228. data/lib/active_record/validations/absence.rb +25 -0
  229. data/lib/active_record/validations/associated.rb +60 -0
  230. data/lib/active_record/validations/length.rb +26 -0
  231. data/lib/active_record/validations/presence.rb +68 -0
  232. data/lib/active_record/validations/uniqueness.rb +238 -0
  233. data/lib/active_record/version.rb +10 -0
  234. data/lib/rails/generators/active_record.rb +19 -0
  235. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  236. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  237. data/lib/rails/generators/active_record/migration.rb +35 -0
  238. data/lib/rails/generators/active_record/migration/migration_generator.rb +78 -0
  239. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  240. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +46 -0
  241. data/lib/rails/generators/active_record/model/model_generator.rb +48 -0
  242. data/lib/rails/generators/active_record/model/templates/model.rb.tt +13 -0
  243. data/lib/rails/generators/active_record/model/templates/module.rb.tt +7 -0
  244. metadata +333 -0
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters # :nodoc:
5
+ module DatabaseLimits
6
+ # Returns the maximum length of a table alias.
7
+ def table_alias_length
8
+ 255
9
+ end
10
+
11
+ # Returns the maximum length of a column name.
12
+ def column_name_length
13
+ 64
14
+ end
15
+
16
+ # Returns the maximum length of a table name.
17
+ def table_name_length
18
+ 64
19
+ end
20
+
21
+ # Returns the maximum allowed length for an index name. This
22
+ # limit is enforced by \Rails and is less than or equal to
23
+ # #index_name_length. The gap between
24
+ # #index_name_length is to allow internal \Rails
25
+ # operations to use prefixes in temporary operations.
26
+ def allowed_index_name_length
27
+ index_name_length
28
+ end
29
+
30
+ # Returns the maximum length of an index name.
31
+ def index_name_length
32
+ 64
33
+ end
34
+
35
+ # Returns the maximum number of columns per table.
36
+ def columns_per_table
37
+ 1024
38
+ end
39
+
40
+ # Returns the maximum number of indexes per table.
41
+ def indexes_per_table
42
+ 16
43
+ end
44
+
45
+ # Returns the maximum number of columns in a multicolumn index.
46
+ def columns_per_multicolumn_index
47
+ 16
48
+ end
49
+
50
+ # Returns the maximum number of elements in an IN (x,y,z) clause.
51
+ # +nil+ means no limit.
52
+ def in_clause_length
53
+ nil
54
+ end
55
+
56
+ # Returns the maximum length of an SQL query.
57
+ def sql_query_length
58
+ 1048575
59
+ end
60
+
61
+ # Returns maximum number of joins in a single query.
62
+ def joins_per_query
63
+ 256
64
+ end
65
+
66
+ private
67
+ def bind_params_length
68
+ 65535
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,540 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ConnectionAdapters # :nodoc:
5
+ module DatabaseStatements
6
+ def initialize
7
+ super
8
+ reset_transaction
9
+ end
10
+
11
+ # Converts an arel AST to SQL
12
+ def to_sql(arel_or_sql_string, binds = [])
13
+ sql, _ = to_sql_and_binds(arel_or_sql_string, binds)
14
+ sql
15
+ end
16
+
17
+ def to_sql_and_binds(arel_or_sql_string, binds = []) # :nodoc:
18
+ if arel_or_sql_string.respond_to?(:ast)
19
+ unless binds.empty?
20
+ raise "Passing bind parameters with an arel AST is forbidden. " \
21
+ "The values must be stored on the AST directly"
22
+ end
23
+
24
+ if prepared_statements
25
+ sql, binds = visitor.accept(arel_or_sql_string.ast, collector).value
26
+
27
+ if binds.length > bind_params_length
28
+ unprepared_statement do
29
+ sql, binds = to_sql_and_binds(arel_or_sql_string)
30
+ visitor.preparable = false
31
+ end
32
+ end
33
+ else
34
+ sql = visitor.accept(arel_or_sql_string.ast, collector).value
35
+ end
36
+ [sql.freeze, binds]
37
+ else
38
+ visitor.preparable = false if prepared_statements
39
+ [arel_or_sql_string.dup.freeze, binds]
40
+ end
41
+ end
42
+ private :to_sql_and_binds
43
+
44
+ # This is used in the StatementCache object. It returns an object that
45
+ # can be used to query the database repeatedly.
46
+ def cacheable_query(klass, arel) # :nodoc:
47
+ if prepared_statements
48
+ sql, binds = visitor.accept(arel.ast, collector).value
49
+ query = klass.query(sql)
50
+ else
51
+ collector = PartialQueryCollector.new
52
+ parts, binds = visitor.accept(arel.ast, collector).value
53
+ query = klass.partial_query(parts)
54
+ end
55
+ [query, binds]
56
+ end
57
+
58
+ # Returns an ActiveRecord::Result instance.
59
+ def select_all(arel, name = nil, binds = [], preparable: nil)
60
+ arel = arel_from_relation(arel)
61
+ sql, binds = to_sql_and_binds(arel, binds)
62
+
63
+ if preparable.nil?
64
+ preparable = prepared_statements ? visitor.preparable : false
65
+ end
66
+
67
+ if prepared_statements && preparable
68
+ select_prepared(sql, name, binds)
69
+ else
70
+ select(sql, name, binds)
71
+ end
72
+ end
73
+
74
+ # Returns a record hash with the column names as keys and column values
75
+ # as values.
76
+ def select_one(arel, name = nil, binds = [])
77
+ select_all(arel, name, binds).first
78
+ end
79
+
80
+ # Returns a single value from a record
81
+ def select_value(arel, name = nil, binds = [])
82
+ single_value_from_rows(select_rows(arel, name, binds))
83
+ end
84
+
85
+ # Returns an array of the values of the first column in a select:
86
+ # select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
87
+ def select_values(arel, name = nil, binds = [])
88
+ select_rows(arel, name, binds).map(&:first)
89
+ end
90
+
91
+ # Returns an array of arrays containing the field values.
92
+ # Order is the same as that returned by +columns+.
93
+ def select_rows(arel, name = nil, binds = [])
94
+ select_all(arel, name, binds).rows
95
+ end
96
+
97
+ def query_value(sql, name = nil) # :nodoc:
98
+ single_value_from_rows(query(sql, name))
99
+ end
100
+
101
+ def query_values(sql, name = nil) # :nodoc:
102
+ query(sql, name).map(&:first)
103
+ end
104
+
105
+ def query(sql, name = nil) # :nodoc:
106
+ exec_query(sql, name).rows
107
+ end
108
+
109
+ # Executes the SQL statement in the context of this connection and returns
110
+ # the raw result from the connection adapter.
111
+ # Note: depending on your database connector, the result returned by this
112
+ # method may be manually memory managed. Consider using the exec_query
113
+ # wrapper instead.
114
+ def execute(sql, name = nil)
115
+ raise NotImplementedError
116
+ end
117
+
118
+ # Executes +sql+ statement in the context of this connection using
119
+ # +binds+ as the bind substitutes. +name+ is logged along with
120
+ # the executed +sql+ statement.
121
+ def exec_query(sql, name = "SQL", binds = [], prepare: false)
122
+ raise NotImplementedError
123
+ end
124
+
125
+ # Executes insert +sql+ statement in the context of this connection using
126
+ # +binds+ as the bind substitutes. +name+ is logged along with
127
+ # the executed +sql+ statement.
128
+ def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
129
+ sql, binds = sql_for_insert(sql, pk, nil, sequence_name, binds)
130
+ exec_query(sql, name, binds)
131
+ end
132
+
133
+ # Executes delete +sql+ statement in the context of this connection using
134
+ # +binds+ as the bind substitutes. +name+ is logged along with
135
+ # the executed +sql+ statement.
136
+ def exec_delete(sql, name = nil, binds = [])
137
+ exec_query(sql, name, binds)
138
+ end
139
+
140
+ # Executes the truncate statement.
141
+ def truncate(table_name, name = nil)
142
+ raise NotImplementedError
143
+ end
144
+
145
+ # Executes update +sql+ statement in the context of this connection using
146
+ # +binds+ as the bind substitutes. +name+ is logged along with
147
+ # the executed +sql+ statement.
148
+ def exec_update(sql, name = nil, binds = [])
149
+ exec_query(sql, name, binds)
150
+ end
151
+
152
+ # Executes an INSERT query and returns the new record's ID
153
+ #
154
+ # +id_value+ will be returned unless the value is +nil+, in
155
+ # which case the database will attempt to calculate the last inserted
156
+ # id and return that value.
157
+ #
158
+ # If the next id was calculated in advance (as in Oracle), it should be
159
+ # passed in as +id_value+.
160
+ def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
161
+ sql, binds = to_sql_and_binds(arel, binds)
162
+ value = exec_insert(sql, name, binds, pk, sequence_name)
163
+ id_value || last_inserted_id(value)
164
+ end
165
+ alias create insert
166
+
167
+ # Executes the update statement and returns the number of rows affected.
168
+ def update(arel, name = nil, binds = [])
169
+ sql, binds = to_sql_and_binds(arel, binds)
170
+ exec_update(sql, name, binds)
171
+ end
172
+
173
+ # Executes the delete statement and returns the number of rows affected.
174
+ def delete(arel, name = nil, binds = [])
175
+ sql, binds = to_sql_and_binds(arel, binds)
176
+ exec_delete(sql, name, binds)
177
+ end
178
+
179
+ # Returns +true+ when the connection adapter supports prepared statement
180
+ # caching, otherwise returns +false+
181
+ def supports_statement_cache? # :nodoc:
182
+ true
183
+ end
184
+ deprecate :supports_statement_cache?
185
+
186
+ # Runs the given block in a database transaction, and returns the result
187
+ # of the block.
188
+ #
189
+ # == Nested transactions support
190
+ #
191
+ # Most databases don't support true nested transactions. At the time of
192
+ # writing, the only database that supports true nested transactions that
193
+ # we're aware of, is MS-SQL.
194
+ #
195
+ # In order to get around this problem, #transaction will emulate the effect
196
+ # of nested transactions, by using savepoints:
197
+ # https://dev.mysql.com/doc/refman/5.7/en/savepoint.html
198
+ # Savepoints are supported by MySQL and PostgreSQL. SQLite3 version >= '3.6.8'
199
+ # supports savepoints.
200
+ #
201
+ # It is safe to call this method if a database transaction is already open,
202
+ # i.e. if #transaction is called within another #transaction block. In case
203
+ # of a nested call, #transaction will behave as follows:
204
+ #
205
+ # - The block will be run without doing anything. All database statements
206
+ # that happen within the block are effectively appended to the already
207
+ # open database transaction.
208
+ # - However, if +:requires_new+ is set, the block will be wrapped in a
209
+ # database savepoint acting as a sub-transaction.
210
+ #
211
+ # === Caveats
212
+ #
213
+ # MySQL doesn't support DDL transactions. If you perform a DDL operation,
214
+ # then any created savepoints will be automatically released. For example,
215
+ # if you've created a savepoint, then you execute a CREATE TABLE statement,
216
+ # then the savepoint that was created will be automatically released.
217
+ #
218
+ # This means that, on MySQL, you shouldn't execute DDL operations inside
219
+ # a #transaction call that you know might create a savepoint. Otherwise,
220
+ # #transaction will raise exceptions when it tries to release the
221
+ # already-automatically-released savepoints:
222
+ #
223
+ # Model.connection.transaction do # BEGIN
224
+ # Model.connection.transaction(requires_new: true) do # CREATE SAVEPOINT active_record_1
225
+ # Model.connection.create_table(...)
226
+ # # active_record_1 now automatically released
227
+ # end # RELEASE SAVEPOINT active_record_1 <--- BOOM! database error!
228
+ # end
229
+ #
230
+ # == Transaction isolation
231
+ #
232
+ # If your database supports setting the isolation level for a transaction, you can set
233
+ # it like so:
234
+ #
235
+ # Post.transaction(isolation: :serializable) do
236
+ # # ...
237
+ # end
238
+ #
239
+ # Valid isolation levels are:
240
+ #
241
+ # * <tt>:read_uncommitted</tt>
242
+ # * <tt>:read_committed</tt>
243
+ # * <tt>:repeatable_read</tt>
244
+ # * <tt>:serializable</tt>
245
+ #
246
+ # You should consult the documentation for your database to understand the
247
+ # semantics of these different levels:
248
+ #
249
+ # * https://www.postgresql.org/docs/current/static/transaction-iso.html
250
+ # * https://dev.mysql.com/doc/refman/5.7/en/set-transaction.html
251
+ #
252
+ # An ActiveRecord::TransactionIsolationError will be raised if:
253
+ #
254
+ # * The adapter does not support setting the isolation level
255
+ # * You are joining an existing open transaction
256
+ # * You are creating a nested (savepoint) transaction
257
+ #
258
+ # The mysql2 and postgresql adapters support setting the transaction
259
+ # isolation level.
260
+ def transaction(requires_new: nil, isolation: nil, joinable: true)
261
+ if !requires_new && current_transaction.joinable?
262
+ if isolation
263
+ raise ActiveRecord::TransactionIsolationError, "cannot set isolation when joining a transaction"
264
+ end
265
+ yield
266
+ else
267
+ transaction_manager.within_new_transaction(isolation: isolation, joinable: joinable) { yield }
268
+ end
269
+ rescue ActiveRecord::Rollback
270
+ # rollbacks are silently swallowed
271
+ end
272
+
273
+ attr_reader :transaction_manager #:nodoc:
274
+
275
+ delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction, :commit_transaction, :rollback_transaction, to: :transaction_manager
276
+
277
+ def transaction_open?
278
+ current_transaction.open?
279
+ end
280
+
281
+ def reset_transaction #:nodoc:
282
+ @transaction_manager = ConnectionAdapters::TransactionManager.new(self)
283
+ end
284
+
285
+ # Register a record with the current transaction so that its after_commit and after_rollback callbacks
286
+ # can be called.
287
+ def add_transaction_record(record)
288
+ current_transaction.add_record(record)
289
+ end
290
+
291
+ def transaction_state
292
+ current_transaction.state
293
+ end
294
+
295
+ # Begins the transaction (and turns off auto-committing).
296
+ def begin_db_transaction() end
297
+
298
+ def transaction_isolation_levels
299
+ {
300
+ read_uncommitted: "READ UNCOMMITTED",
301
+ read_committed: "READ COMMITTED",
302
+ repeatable_read: "REPEATABLE READ",
303
+ serializable: "SERIALIZABLE"
304
+ }
305
+ end
306
+
307
+ # Begins the transaction with the isolation level set. Raises an error by
308
+ # default; adapters that support setting the isolation level should implement
309
+ # this method.
310
+ def begin_isolated_db_transaction(isolation)
311
+ raise ActiveRecord::TransactionIsolationError, "adapter does not support setting transaction isolation"
312
+ end
313
+
314
+ # Commits the transaction (and turns on auto-committing).
315
+ def commit_db_transaction() end
316
+
317
+ # Rolls back the transaction (and turns on auto-committing). Must be
318
+ # done if the transaction block raises an exception or returns false.
319
+ def rollback_db_transaction
320
+ exec_rollback_db_transaction
321
+ end
322
+
323
+ def exec_rollback_db_transaction() end #:nodoc:
324
+
325
+ def rollback_to_savepoint(name = nil)
326
+ exec_rollback_to_savepoint(name)
327
+ end
328
+
329
+ def default_sequence_name(table, column)
330
+ nil
331
+ end
332
+
333
+ # Set the sequence to the max value of the table's column.
334
+ def reset_sequence!(table, column, sequence = nil)
335
+ # Do nothing by default. Implement for PostgreSQL, Oracle, ...
336
+ end
337
+
338
+ # Inserts the given fixture into the table. Overridden in adapters that require
339
+ # something beyond a simple insert (eg. Oracle).
340
+ # Most of adapters should implement `insert_fixtures` that leverages bulk SQL insert.
341
+ # We keep this method to provide fallback
342
+ # for databases like sqlite that do not support bulk inserts.
343
+ def insert_fixture(fixture, table_name)
344
+ fixture = fixture.stringify_keys
345
+
346
+ columns = schema_cache.columns_hash(table_name)
347
+ binds = fixture.map do |name, value|
348
+ if column = columns[name]
349
+ type = lookup_cast_type_from_column(column)
350
+ Relation::QueryAttribute.new(name, value, type)
351
+ else
352
+ raise Fixture::FixtureError, %(table "#{table_name}" has no column named #{name.inspect}.)
353
+ end
354
+ end
355
+
356
+ table = Arel::Table.new(table_name)
357
+
358
+ values = binds.map do |bind|
359
+ value = with_yaml_fallback(bind.value_for_database)
360
+ [table[bind.name], value]
361
+ end
362
+
363
+ manager = Arel::InsertManager.new
364
+ manager.into(table)
365
+ manager.insert(values)
366
+ execute manager.to_sql, "Fixture Insert"
367
+ end
368
+
369
+ # Inserts a set of fixtures into the table. Overridden in adapters that require
370
+ # something beyond a simple insert (eg. Oracle).
371
+ def insert_fixtures(fixtures, table_name)
372
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
373
+ `insert_fixtures` is deprecated and will be removed in the next version of Rails.
374
+ Consider using `insert_fixtures_set` for performance improvement.
375
+ MSG
376
+ return if fixtures.empty?
377
+
378
+ execute(build_fixture_sql(fixtures, table_name), "Fixtures Insert")
379
+ end
380
+
381
+ def insert_fixtures_set(fixture_set, tables_to_delete = [])
382
+ fixture_inserts = fixture_set.map do |table_name, fixtures|
383
+ next if fixtures.empty?
384
+
385
+ build_fixture_sql(fixtures, table_name)
386
+ end.compact
387
+
388
+ table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name table}".dup }
389
+ total_sql = Array.wrap(combine_multi_statements(table_deletes + fixture_inserts))
390
+
391
+ disable_referential_integrity do
392
+ transaction(requires_new: true) do
393
+ total_sql.each do |sql|
394
+ execute sql, "Fixtures Load"
395
+ yield if block_given?
396
+ end
397
+ end
398
+ end
399
+ end
400
+
401
+ def empty_insert_statement_value
402
+ "DEFAULT VALUES"
403
+ end
404
+
405
+ # Sanitizes the given LIMIT parameter in order to prevent SQL injection.
406
+ #
407
+ # The +limit+ may be anything that can evaluate to a string via #to_s. It
408
+ # should look like an integer, or an Arel SQL literal.
409
+ #
410
+ # Returns Integer and Arel::Nodes::SqlLiteral limits as is.
411
+ def sanitize_limit(limit)
412
+ if limit.is_a?(Integer) || limit.is_a?(Arel::Nodes::SqlLiteral)
413
+ limit
414
+ else
415
+ Integer(limit)
416
+ end
417
+ end
418
+
419
+ # The default strategy for an UPDATE with joins is to use a subquery. This doesn't work
420
+ # on MySQL (even when aliasing the tables), but MySQL allows using JOIN directly in
421
+ # an UPDATE statement, so in the MySQL adapters we redefine this to do that.
422
+ def join_to_update(update, select, key) # :nodoc:
423
+ subselect = subquery_for(key, select)
424
+
425
+ update.where key.in(subselect)
426
+ end
427
+ alias join_to_delete join_to_update
428
+
429
+ private
430
+ def default_insert_value(column)
431
+ Arel.sql("DEFAULT")
432
+ end
433
+
434
+ def build_fixture_sql(fixtures, table_name)
435
+ columns = schema_cache.columns_hash(table_name)
436
+
437
+ values = fixtures.map do |fixture|
438
+ fixture = fixture.stringify_keys
439
+
440
+ unknown_columns = fixture.keys - columns.keys
441
+ if unknown_columns.any?
442
+ raise Fixture::FixtureError, %(table "#{table_name}" has no columns named #{unknown_columns.map(&:inspect).join(', ')}.)
443
+ end
444
+
445
+ columns.map do |name, column|
446
+ if fixture.key?(name)
447
+ type = lookup_cast_type_from_column(column)
448
+ bind = Relation::QueryAttribute.new(name, fixture[name], type)
449
+ with_yaml_fallback(bind.value_for_database)
450
+ else
451
+ default_insert_value(column)
452
+ end
453
+ end
454
+ end
455
+
456
+ table = Arel::Table.new(table_name)
457
+ manager = Arel::InsertManager.new
458
+ manager.into(table)
459
+ columns.each_key { |column| manager.columns << table[column] }
460
+ manager.values = manager.create_values_list(values)
461
+
462
+ manager.to_sql
463
+ end
464
+
465
+ def combine_multi_statements(total_sql)
466
+ total_sql.join(";\n")
467
+ end
468
+
469
+ # Returns a subquery for the given key using the join information.
470
+ def subquery_for(key, select)
471
+ subselect = select.clone
472
+ subselect.projections = [key]
473
+ subselect
474
+ end
475
+
476
+ # Returns an ActiveRecord::Result instance.
477
+ def select(sql, name = nil, binds = [])
478
+ exec_query(sql, name, binds, prepare: false)
479
+ end
480
+
481
+ def select_prepared(sql, name = nil, binds = [])
482
+ exec_query(sql, name, binds, prepare: true)
483
+ end
484
+
485
+ def sql_for_insert(sql, pk, id_value, sequence_name, binds)
486
+ [sql, binds]
487
+ end
488
+
489
+ def last_inserted_id(result)
490
+ single_value_from_rows(result.rows)
491
+ end
492
+
493
+ def single_value_from_rows(rows)
494
+ row = rows.first
495
+ row && row.first
496
+ end
497
+
498
+ def arel_from_relation(relation)
499
+ if relation.is_a?(Relation)
500
+ relation.arel
501
+ else
502
+ relation
503
+ end
504
+ end
505
+
506
+ # Fixture value is quoted by Arel, however scalar values
507
+ # are not quotable. In this case we want to convert
508
+ # the column value to YAML.
509
+ def with_yaml_fallback(value)
510
+ if value.is_a?(Hash) || value.is_a?(Array)
511
+ YAML.dump(value)
512
+ else
513
+ value
514
+ end
515
+ end
516
+
517
+ class PartialQueryCollector
518
+ def initialize
519
+ @parts = []
520
+ @binds = []
521
+ end
522
+
523
+ def <<(str)
524
+ @parts << str
525
+ self
526
+ end
527
+
528
+ def add_bind(obj)
529
+ @binds << obj
530
+ @parts << Arel::Nodes::BindParam.new(1)
531
+ self
532
+ end
533
+
534
+ def value
535
+ [@parts, @binds]
536
+ end
537
+ end
538
+ end
539
+ end
540
+ end