activerecord 5.2.6 → 6.0.5

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 (294) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +928 -559
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +5 -3
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record/advisory_lock_base.rb +18 -0
  7. data/lib/active_record/aggregations.rb +4 -3
  8. data/lib/active_record/association_relation.rb +10 -8
  9. data/lib/active_record/associations/alias_tracker.rb +0 -1
  10. data/lib/active_record/associations/association.rb +55 -19
  11. data/lib/active_record/associations/association_scope.rb +11 -7
  12. data/lib/active_record/associations/belongs_to_association.rb +36 -42
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
  14. data/lib/active_record/associations/builder/association.rb +14 -18
  15. data/lib/active_record/associations/builder/belongs_to.rb +19 -52
  16. data/lib/active_record/associations/builder/collection_association.rb +3 -13
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -40
  18. data/lib/active_record/associations/builder/has_many.rb +2 -0
  19. data/lib/active_record/associations/builder/has_one.rb +35 -1
  20. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  21. data/lib/active_record/associations/collection_association.rb +19 -23
  22. data/lib/active_record/associations/collection_proxy.rb +14 -17
  23. data/lib/active_record/associations/foreign_association.rb +7 -0
  24. data/lib/active_record/associations/has_many_association.rb +2 -11
  25. data/lib/active_record/associations/has_many_through_association.rb +14 -14
  26. data/lib/active_record/associations/has_one_association.rb +28 -30
  27. data/lib/active_record/associations/has_one_through_association.rb +5 -5
  28. data/lib/active_record/associations/join_dependency/join_association.rb +16 -10
  29. data/lib/active_record/associations/join_dependency/join_part.rb +4 -4
  30. data/lib/active_record/associations/join_dependency.rb +47 -30
  31. data/lib/active_record/associations/preloader/association.rb +61 -41
  32. data/lib/active_record/associations/preloader/through_association.rb +48 -39
  33. data/lib/active_record/associations/preloader.rb +44 -33
  34. data/lib/active_record/associations/singular_association.rb +2 -16
  35. data/lib/active_record/associations/through_association.rb +1 -1
  36. data/lib/active_record/associations.rb +21 -16
  37. data/lib/active_record/attribute_assignment.rb +7 -11
  38. data/lib/active_record/attribute_decorators.rb +0 -2
  39. data/lib/active_record/attribute_methods/before_type_cast.rb +4 -2
  40. data/lib/active_record/attribute_methods/dirty.rb +111 -40
  41. data/lib/active_record/attribute_methods/primary_key.rb +15 -24
  42. data/lib/active_record/attribute_methods/query.rb +2 -3
  43. data/lib/active_record/attribute_methods/read.rb +15 -54
  44. data/lib/active_record/attribute_methods/serialization.rb +1 -2
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -3
  46. data/lib/active_record/attribute_methods/write.rb +17 -25
  47. data/lib/active_record/attribute_methods.rb +28 -100
  48. data/lib/active_record/attributes.rb +13 -1
  49. data/lib/active_record/autosave_association.rb +12 -14
  50. data/lib/active_record/base.rb +2 -3
  51. data/lib/active_record/callbacks.rb +6 -21
  52. data/lib/active_record/coders/yaml_column.rb +0 -1
  53. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +109 -18
  54. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -4
  55. data/lib/active_record/connection_adapters/abstract/database_statements.rb +102 -124
  56. data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -9
  57. data/lib/active_record/connection_adapters/abstract/quoting.rb +68 -17
  58. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +20 -14
  59. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +105 -72
  60. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -3
  61. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +175 -79
  62. data/lib/active_record/connection_adapters/abstract/transaction.rb +96 -57
  63. data/lib/active_record/connection_adapters/abstract_adapter.rb +197 -43
  64. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +149 -217
  65. data/lib/active_record/connection_adapters/column.rb +17 -13
  66. data/lib/active_record/connection_adapters/connection_specification.rb +54 -45
  67. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +6 -10
  68. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  69. data/lib/active_record/connection_adapters/mysql/database_statements.rb +70 -14
  70. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +0 -1
  71. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
  72. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +4 -6
  73. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +40 -32
  74. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +14 -6
  75. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +139 -19
  76. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +6 -10
  77. data/lib/active_record/connection_adapters/mysql2_adapter.rb +26 -10
  78. data/lib/active_record/connection_adapters/postgresql/column.rb +17 -31
  79. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +26 -1
  80. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  81. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  82. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +8 -0
  83. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  84. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
  89. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
  91. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +5 -3
  92. data/lib/active_record/connection_adapters/postgresql/quoting.rb +44 -7
  93. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
  94. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +14 -3
  95. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
  96. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  97. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +63 -75
  98. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +24 -27
  99. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  100. data/lib/active_record/connection_adapters/postgresql_adapter.rb +168 -75
  101. data/lib/active_record/connection_adapters/schema_cache.rb +37 -14
  102. data/lib/active_record/connection_adapters/sql_type_metadata.rb +11 -8
  103. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -0
  104. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
  105. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -12
  106. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +137 -147
  107. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  108. data/lib/active_record/connection_handling.rb +139 -26
  109. data/lib/active_record/core.rb +107 -66
  110. data/lib/active_record/counter_cache.rb +8 -30
  111. data/lib/active_record/database_configurations/database_config.rb +37 -0
  112. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  113. data/lib/active_record/database_configurations/url_config.rb +78 -0
  114. data/lib/active_record/database_configurations.rb +233 -0
  115. data/lib/active_record/dynamic_matchers.rb +3 -4
  116. data/lib/active_record/enum.rb +44 -7
  117. data/lib/active_record/errors.rb +15 -7
  118. data/lib/active_record/explain.rb +1 -2
  119. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  120. data/lib/active_record/fixture_set/render_context.rb +17 -0
  121. data/lib/active_record/fixture_set/table_row.rb +152 -0
  122. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  123. data/lib/active_record/fixtures.rb +144 -474
  124. data/lib/active_record/gem_version.rb +3 -3
  125. data/lib/active_record/inheritance.rb +13 -6
  126. data/lib/active_record/insert_all.rb +179 -0
  127. data/lib/active_record/integration.rb +68 -16
  128. data/lib/active_record/internal_metadata.rb +11 -3
  129. data/lib/active_record/locking/optimistic.rb +14 -7
  130. data/lib/active_record/locking/pessimistic.rb +3 -3
  131. data/lib/active_record/log_subscriber.rb +8 -27
  132. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  133. data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
  134. data/lib/active_record/middleware/database_selector.rb +74 -0
  135. data/lib/active_record/migration/command_recorder.rb +54 -22
  136. data/lib/active_record/migration/compatibility.rb +79 -52
  137. data/lib/active_record/migration/join_table.rb +0 -1
  138. data/lib/active_record/migration.rb +104 -85
  139. data/lib/active_record/model_schema.rb +62 -11
  140. data/lib/active_record/nested_attributes.rb +2 -4
  141. data/lib/active_record/no_touching.rb +9 -2
  142. data/lib/active_record/null_relation.rb +0 -1
  143. data/lib/active_record/persistence.rb +232 -29
  144. data/lib/active_record/query_cache.rb +11 -4
  145. data/lib/active_record/querying.rb +33 -21
  146. data/lib/active_record/railtie.rb +80 -43
  147. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  148. data/lib/active_record/railties/controller_runtime.rb +30 -35
  149. data/lib/active_record/railties/databases.rake +199 -46
  150. data/lib/active_record/reflection.rb +51 -51
  151. data/lib/active_record/relation/batches.rb +13 -11
  152. data/lib/active_record/relation/calculations.rb +55 -49
  153. data/lib/active_record/relation/delegation.rb +35 -50
  154. data/lib/active_record/relation/finder_methods.rb +23 -28
  155. data/lib/active_record/relation/from_clause.rb +4 -0
  156. data/lib/active_record/relation/merger.rb +12 -17
  157. data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
  158. data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
  159. data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
  160. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  161. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
  162. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  163. data/lib/active_record/relation/predicate_builder.rb +5 -11
  164. data/lib/active_record/relation/query_attribute.rb +13 -8
  165. data/lib/active_record/relation/query_methods.rb +232 -69
  166. data/lib/active_record/relation/spawn_methods.rb +1 -2
  167. data/lib/active_record/relation/where_clause.rb +14 -11
  168. data/lib/active_record/relation/where_clause_factory.rb +1 -2
  169. data/lib/active_record/relation.rb +326 -81
  170. data/lib/active_record/result.rb +30 -12
  171. data/lib/active_record/sanitization.rb +32 -40
  172. data/lib/active_record/schema.rb +2 -11
  173. data/lib/active_record/schema_dumper.rb +22 -7
  174. data/lib/active_record/schema_migration.rb +6 -2
  175. data/lib/active_record/scoping/default.rb +4 -6
  176. data/lib/active_record/scoping/named.rb +25 -16
  177. data/lib/active_record/scoping.rb +8 -9
  178. data/lib/active_record/statement_cache.rb +30 -3
  179. data/lib/active_record/store.rb +87 -8
  180. data/lib/active_record/suppressor.rb +2 -2
  181. data/lib/active_record/table_metadata.rb +23 -15
  182. data/lib/active_record/tasks/database_tasks.rb +194 -25
  183. data/lib/active_record/tasks/mysql_database_tasks.rb +5 -6
  184. data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -8
  185. data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -9
  186. data/lib/active_record/test_databases.rb +23 -0
  187. data/lib/active_record/test_fixtures.rb +243 -0
  188. data/lib/active_record/timestamp.rb +39 -26
  189. data/lib/active_record/touch_later.rb +5 -4
  190. data/lib/active_record/transactions.rb +64 -73
  191. data/lib/active_record/translation.rb +1 -1
  192. data/lib/active_record/type/adapter_specific_registry.rb +3 -13
  193. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  194. data/lib/active_record/type/serialized.rb +0 -1
  195. data/lib/active_record/type/time.rb +10 -0
  196. data/lib/active_record/type/type_map.rb +0 -1
  197. data/lib/active_record/type/unsigned_integer.rb +0 -1
  198. data/lib/active_record/type.rb +3 -5
  199. data/lib/active_record/type_caster/connection.rb +15 -14
  200. data/lib/active_record/type_caster/map.rb +1 -4
  201. data/lib/active_record/validations/associated.rb +0 -1
  202. data/lib/active_record/validations/uniqueness.rb +15 -27
  203. data/lib/active_record/validations.rb +3 -3
  204. data/lib/active_record.rb +10 -2
  205. data/lib/arel/alias_predication.rb +9 -0
  206. data/lib/arel/attributes/attribute.rb +37 -0
  207. data/lib/arel/attributes.rb +22 -0
  208. data/lib/arel/collectors/bind.rb +24 -0
  209. data/lib/arel/collectors/composite.rb +31 -0
  210. data/lib/arel/collectors/plain_string.rb +20 -0
  211. data/lib/arel/collectors/sql_string.rb +20 -0
  212. data/lib/arel/collectors/substitute_binds.rb +28 -0
  213. data/lib/arel/crud.rb +42 -0
  214. data/lib/arel/delete_manager.rb +18 -0
  215. data/lib/arel/errors.rb +9 -0
  216. data/lib/arel/expressions.rb +29 -0
  217. data/lib/arel/factory_methods.rb +49 -0
  218. data/lib/arel/insert_manager.rb +49 -0
  219. data/lib/arel/math.rb +45 -0
  220. data/lib/arel/nodes/and.rb +32 -0
  221. data/lib/arel/nodes/ascending.rb +23 -0
  222. data/lib/arel/nodes/binary.rb +52 -0
  223. data/lib/arel/nodes/bind_param.rb +36 -0
  224. data/lib/arel/nodes/case.rb +55 -0
  225. data/lib/arel/nodes/casted.rb +50 -0
  226. data/lib/arel/nodes/comment.rb +29 -0
  227. data/lib/arel/nodes/count.rb +12 -0
  228. data/lib/arel/nodes/delete_statement.rb +45 -0
  229. data/lib/arel/nodes/descending.rb +23 -0
  230. data/lib/arel/nodes/equality.rb +18 -0
  231. data/lib/arel/nodes/extract.rb +24 -0
  232. data/lib/arel/nodes/false.rb +16 -0
  233. data/lib/arel/nodes/full_outer_join.rb +8 -0
  234. data/lib/arel/nodes/function.rb +44 -0
  235. data/lib/arel/nodes/grouping.rb +8 -0
  236. data/lib/arel/nodes/in.rb +8 -0
  237. data/lib/arel/nodes/infix_operation.rb +80 -0
  238. data/lib/arel/nodes/inner_join.rb +8 -0
  239. data/lib/arel/nodes/insert_statement.rb +37 -0
  240. data/lib/arel/nodes/join_source.rb +20 -0
  241. data/lib/arel/nodes/matches.rb +18 -0
  242. data/lib/arel/nodes/named_function.rb +23 -0
  243. data/lib/arel/nodes/node.rb +50 -0
  244. data/lib/arel/nodes/node_expression.rb +13 -0
  245. data/lib/arel/nodes/outer_join.rb +8 -0
  246. data/lib/arel/nodes/over.rb +15 -0
  247. data/lib/arel/nodes/regexp.rb +16 -0
  248. data/lib/arel/nodes/right_outer_join.rb +8 -0
  249. data/lib/arel/nodes/select_core.rb +67 -0
  250. data/lib/arel/nodes/select_statement.rb +41 -0
  251. data/lib/arel/nodes/sql_literal.rb +16 -0
  252. data/lib/arel/nodes/string_join.rb +11 -0
  253. data/lib/arel/nodes/table_alias.rb +27 -0
  254. data/lib/arel/nodes/terminal.rb +16 -0
  255. data/lib/arel/nodes/true.rb +16 -0
  256. data/lib/arel/nodes/unary.rb +45 -0
  257. data/lib/arel/nodes/unary_operation.rb +20 -0
  258. data/lib/arel/nodes/unqualified_column.rb +22 -0
  259. data/lib/arel/nodes/update_statement.rb +41 -0
  260. data/lib/arel/nodes/values_list.rb +9 -0
  261. data/lib/arel/nodes/window.rb +126 -0
  262. data/lib/arel/nodes/with.rb +11 -0
  263. data/lib/arel/nodes.rb +68 -0
  264. data/lib/arel/order_predications.rb +13 -0
  265. data/lib/arel/predications.rb +256 -0
  266. data/lib/arel/select_manager.rb +271 -0
  267. data/lib/arel/table.rb +110 -0
  268. data/lib/arel/tree_manager.rb +72 -0
  269. data/lib/arel/update_manager.rb +34 -0
  270. data/lib/arel/visitors/depth_first.rb +203 -0
  271. data/lib/arel/visitors/dot.rb +296 -0
  272. data/lib/arel/visitors/ibm_db.rb +34 -0
  273. data/lib/arel/visitors/informix.rb +62 -0
  274. data/lib/arel/visitors/mssql.rb +156 -0
  275. data/lib/arel/visitors/mysql.rb +83 -0
  276. data/lib/arel/visitors/oracle.rb +158 -0
  277. data/lib/arel/visitors/oracle12.rb +65 -0
  278. data/lib/arel/visitors/postgresql.rb +109 -0
  279. data/lib/arel/visitors/sqlite.rb +38 -0
  280. data/lib/arel/visitors/to_sql.rb +888 -0
  281. data/lib/arel/visitors/visitor.rb +45 -0
  282. data/lib/arel/visitors/where_sql.rb +22 -0
  283. data/lib/arel/visitors.rb +20 -0
  284. data/lib/arel/window_predications.rb +9 -0
  285. data/lib/arel.rb +62 -0
  286. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  287. data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
  288. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +1 -1
  289. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -2
  290. data/lib/rails/generators/active_record/migration.rb +14 -2
  291. data/lib/rails/generators/active_record/model/model_generator.rb +1 -1
  292. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  293. metadata +116 -29
  294. data/lib/active_record/collection_cache_key.rb +0 -53
@@ -4,17 +4,20 @@ require "active_record/connection_adapters/abstract_adapter"
4
4
  require "active_record/connection_adapters/statement_pool"
5
5
  require "active_record/connection_adapters/sqlite3/explain_pretty_printer"
6
6
  require "active_record/connection_adapters/sqlite3/quoting"
7
+ require "active_record/connection_adapters/sqlite3/database_statements"
7
8
  require "active_record/connection_adapters/sqlite3/schema_creation"
8
9
  require "active_record/connection_adapters/sqlite3/schema_definitions"
9
10
  require "active_record/connection_adapters/sqlite3/schema_dumper"
10
11
  require "active_record/connection_adapters/sqlite3/schema_statements"
11
12
 
12
- gem "sqlite3", "~> 1.3", ">= 1.3.6"
13
+ gem "sqlite3", "~> 1.4"
13
14
  require "sqlite3"
14
15
 
15
16
  module ActiveRecord
16
17
  module ConnectionHandling # :nodoc:
17
18
  def sqlite3_connection(config)
19
+ config = config.symbolize_keys
20
+
18
21
  # Require database.
19
22
  unless config[:database]
20
23
  raise ArgumentError, "No database file specified. Missing argument: database"
@@ -31,11 +34,9 @@ module ActiveRecord
31
34
 
32
35
  db = SQLite3::Database.new(
33
36
  config[:database].to_s,
34
- results_as_hash: true
37
+ config.merge(results_as_hash: true)
35
38
  )
36
39
 
37
- db.busy_timeout(ConnectionAdapters::SQLite3Adapter.type_cast_config_to_integer(config[:timeout])) if config[:timeout]
38
-
39
40
  ConnectionAdapters::SQLite3Adapter.new(db, logger, nil, config)
40
41
  rescue Errno::ENOENT => error
41
42
  if error.message.include?("No such file or directory")
@@ -54,10 +55,11 @@ module ActiveRecord
54
55
  #
55
56
  # * <tt>:database</tt> - Path to the database file.
56
57
  class SQLite3Adapter < AbstractAdapter
57
- ADAPTER_NAME = "SQLite".freeze
58
+ ADAPTER_NAME = "SQLite"
58
59
 
59
60
  include SQLite3::Quoting
60
61
  include SQLite3::SchemaStatements
62
+ include SQLite3::DatabaseStatements
61
63
 
62
64
  NATIVE_DATABASE_TYPES = {
63
65
  primary_key: "integer PRIMARY KEY AUTOINCREMENT NOT NULL",
@@ -74,39 +76,38 @@ module ActiveRecord
74
76
  json: { name: "json" },
75
77
  }
76
78
 
77
- ##
78
- # :singleton-method:
79
- # Indicates whether boolean values are stored in sqlite3 databases as 1
80
- # and 0 or 't' and 'f'. Leaving <tt>ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer</tt>
81
- # set to false is deprecated. SQLite databases have used 't' and 'f' to
82
- # serialize boolean values and must have old data converted to 1 and 0
83
- # (its native boolean serialization) before setting this flag to true.
84
- # Conversion can be accomplished by setting up a rake task which runs
85
- #
86
- # ExampleModel.where("boolean_column = 't'").update_all(boolean_column: 1)
87
- # ExampleModel.where("boolean_column = 'f'").update_all(boolean_column: 0)
88
- # for all models and all boolean columns, after which the flag must be set
89
- # to true by adding the following to your <tt>application.rb</tt> file:
90
- #
91
- # Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
92
- class_attribute :represent_boolean_as_integer, default: false
79
+ def self.represent_boolean_as_integer=(value) # :nodoc:
80
+ if value == false
81
+ raise "`.represent_boolean_as_integer=` is now always true, so make sure your application can work with it and remove this settings."
82
+ end
83
+
84
+ ActiveSupport::Deprecation.warn(
85
+ "`.represent_boolean_as_integer=` is now always true, so setting this is deprecated and will be removed in Rails 6.1."
86
+ )
87
+ end
93
88
 
94
89
  class StatementPool < ConnectionAdapters::StatementPool # :nodoc:
95
90
  private
96
91
  def dealloc(stmt)
97
- stmt[:stmt].close unless stmt[:stmt].closed?
92
+ stmt.close unless stmt.closed?
98
93
  end
99
94
  end
100
95
 
101
96
  def initialize(connection, logger, connection_options, config)
102
97
  super(connection, logger, config)
103
-
104
- @active = true
105
- @statements = StatementPool.new(self.class.type_cast_config_to_integer(config[:statement_limit]))
106
-
107
98
  configure_connection
108
99
  end
109
100
 
101
+ def self.database_exists?(config)
102
+ config = config.symbolize_keys
103
+ if config[:database] == ":memory:"
104
+ true
105
+ else
106
+ database_file = defined?(Rails.root) ? File.expand_path(config[:database], Rails.root) : config[:database]
107
+ File.exist?(database_file)
108
+ end
109
+ end
110
+
110
111
  def supports_ddl_transactions?
111
112
  true
112
113
  end
@@ -116,15 +117,19 @@ module ActiveRecord
116
117
  end
117
118
 
118
119
  def supports_partial_index?
119
- sqlite_version >= "3.8.0"
120
+ true
121
+ end
122
+
123
+ def supports_expression_index?
124
+ database_version >= "3.9.0"
120
125
  end
121
126
 
122
127
  def requires_reloading?
123
128
  true
124
129
  end
125
130
 
126
- def supports_foreign_keys_in_create?
127
- sqlite_version >= "3.6.19"
131
+ def supports_foreign_keys?
132
+ true
128
133
  end
129
134
 
130
135
  def supports_views?
@@ -139,27 +144,33 @@ module ActiveRecord
139
144
  true
140
145
  end
141
146
 
142
- def supports_multi_insert?
143
- sqlite_version >= "3.7.11"
147
+ def supports_common_table_expressions?
148
+ database_version >= "3.8.3"
149
+ end
150
+
151
+ def supports_insert_on_conflict?
152
+ database_version >= "3.24.0"
144
153
  end
154
+ alias supports_insert_on_duplicate_skip? supports_insert_on_conflict?
155
+ alias supports_insert_on_duplicate_update? supports_insert_on_conflict?
156
+ alias supports_insert_conflict_target? supports_insert_on_conflict?
145
157
 
146
158
  def active?
147
- @active
159
+ !@connection.closed?
160
+ end
161
+
162
+ def reconnect!
163
+ super
164
+ connect if @connection.closed?
148
165
  end
149
166
 
150
167
  # Disconnects from the database if already connected. Otherwise, this
151
168
  # method does nothing.
152
169
  def disconnect!
153
170
  super
154
- @active = false
155
171
  @connection.close rescue nil
156
172
  end
157
173
 
158
- # Clears the prepared statements cache.
159
- def clear_cache!
160
- @statements.clear
161
- end
162
-
163
174
  def supports_index_sort_order?
164
175
  true
165
176
  end
@@ -184,91 +195,34 @@ module ActiveRecord
184
195
  true
185
196
  end
186
197
 
198
+ def supports_lazy_transactions?
199
+ true
200
+ end
201
+
187
202
  # REFERENTIAL INTEGRITY ====================================
188
203
 
189
204
  def disable_referential_integrity # :nodoc:
190
- old = query_value("PRAGMA foreign_keys")
205
+ old_foreign_keys = query_value("PRAGMA foreign_keys")
206
+ old_defer_foreign_keys = query_value("PRAGMA defer_foreign_keys")
191
207
 
192
208
  begin
209
+ execute("PRAGMA defer_foreign_keys = ON")
193
210
  execute("PRAGMA foreign_keys = OFF")
194
211
  yield
195
212
  ensure
196
- execute("PRAGMA foreign_keys = #{old}")
213
+ execute("PRAGMA defer_foreign_keys = #{old_defer_foreign_keys}")
214
+ execute("PRAGMA foreign_keys = #{old_foreign_keys}")
197
215
  end
198
216
  end
199
217
 
200
218
  #--
201
219
  # DATABASE STATEMENTS ======================================
202
220
  #++
203
-
204
221
  def explain(arel, binds = [])
205
222
  sql = "EXPLAIN QUERY PLAN #{to_sql(arel, binds)}"
206
223
  SQLite3::ExplainPrettyPrinter.new.pp(exec_query(sql, "EXPLAIN", []))
207
224
  end
208
225
 
209
- def exec_query(sql, name = nil, binds = [], prepare: false)
210
- type_casted_binds = type_casted_binds(binds)
211
-
212
- log(sql, name, binds, type_casted_binds) do
213
- ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
214
- # Don't cache statements if they are not prepared
215
- unless prepare
216
- stmt = @connection.prepare(sql)
217
- begin
218
- cols = stmt.columns
219
- unless without_prepared_statement?(binds)
220
- stmt.bind_params(type_casted_binds)
221
- end
222
- records = stmt.to_a
223
- ensure
224
- stmt.close
225
- end
226
- else
227
- cache = @statements[sql] ||= {
228
- stmt: @connection.prepare(sql)
229
- }
230
- stmt = cache[:stmt]
231
- cols = cache[:cols] ||= stmt.columns
232
- stmt.reset!
233
- stmt.bind_params(type_casted_binds)
234
- records = stmt.to_a
235
- end
236
-
237
- ActiveRecord::Result.new(cols, records)
238
- end
239
- end
240
- end
241
-
242
- def exec_delete(sql, name = "SQL", binds = [])
243
- exec_query(sql, name, binds)
244
- @connection.changes
245
- end
246
- alias :exec_update :exec_delete
247
-
248
- def last_inserted_id(result)
249
- @connection.last_insert_row_id
250
- end
251
-
252
- def execute(sql, name = nil) #:nodoc:
253
- log(sql, name) do
254
- ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
255
- @connection.execute(sql)
256
- end
257
- end
258
- end
259
-
260
- def begin_db_transaction #:nodoc:
261
- log("begin transaction", nil) { @connection.transaction }
262
- end
263
-
264
- def commit_db_transaction #:nodoc:
265
- log("commit transaction", nil) { @connection.commit }
266
- end
267
-
268
- def exec_rollback_db_transaction #:nodoc:
269
- log("rollback transaction", nil) { @connection.rollback }
270
- end
271
-
272
226
  # SCHEMA STATEMENTS ========================================
273
227
 
274
228
  def primary_keys(table_name) # :nodoc:
@@ -290,24 +244,22 @@ module ActiveRecord
290
244
  rename_table_indexes(table_name, new_name)
291
245
  end
292
246
 
293
- def valid_alter_table_type?(type, options = {})
294
- !invalid_alter_table_type?(type, options)
295
- end
296
- deprecate :valid_alter_table_type?
297
-
298
- def add_column(table_name, column_name, type, options = {}) #:nodoc:
247
+ def add_column(table_name, column_name, type, **options) #:nodoc:
299
248
  if invalid_alter_table_type?(type, options)
300
249
  alter_table(table_name) do |definition|
301
- definition.column(column_name, type, options)
250
+ definition.column(column_name, type, **options)
302
251
  end
303
252
  else
304
253
  super
305
254
  end
306
255
  end
307
256
 
308
- def remove_column(table_name, column_name, type = nil, options = {}) #:nodoc:
257
+ def remove_column(table_name, column_name, type = nil, **options) #:nodoc:
309
258
  alter_table(table_name) do |definition|
310
259
  definition.remove_column column_name
260
+ definition.foreign_keys.delete_if do |_, fk_options|
261
+ fk_options[:column] == column_name.to_s
262
+ end
311
263
  end
312
264
  end
313
265
 
@@ -331,13 +283,14 @@ module ActiveRecord
331
283
  def change_column(table_name, column_name, type, options = {}) #:nodoc:
332
284
  alter_table(table_name) do |definition|
333
285
  definition[column_name].instance_eval do
334
- self.type = type
286
+ self.type = aliased_types(type.to_s, type)
335
287
  self.limit = options[:limit] if options.include?(:limit)
336
288
  self.default = options[:default] if options.include?(:default)
337
289
  self.null = options[:null] if options.include?(:null)
338
290
  self.precision = options[:precision] if options.include?(:precision)
339
291
  self.scale = options[:scale] if options.include?(:scale)
340
292
  self.collation = options[:collation] if options.include?(:collation)
293
+ self.options.merge!(options)
341
294
  end
342
295
  end
343
296
  end
@@ -366,27 +319,36 @@ module ActiveRecord
366
319
  end
367
320
  end
368
321
 
369
- def insert_fixtures(rows, table_name)
370
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
371
- `insert_fixtures` is deprecated and will be removed in the next version of Rails.
372
- Consider using `insert_fixtures_set` for performance improvement.
373
- MSG
374
- insert_fixtures_set(table_name => rows)
322
+ def build_insert_sql(insert) # :nodoc:
323
+ sql = +"INSERT #{insert.into} #{insert.values_list}"
324
+
325
+ if insert.skip_duplicates?
326
+ sql << " ON CONFLICT #{insert.conflict_target} DO NOTHING"
327
+ elsif insert.update_duplicates?
328
+ sql << " ON CONFLICT #{insert.conflict_target} DO UPDATE SET "
329
+ sql << insert.updatable_columns.map { |column| "#{column}=excluded.#{column}" }.join(",")
330
+ end
331
+
332
+ sql
375
333
  end
376
334
 
377
- def insert_fixtures_set(fixture_set, tables_to_delete = [])
378
- disable_referential_integrity do
379
- transaction(requires_new: true) do
380
- tables_to_delete.each { |table| delete "DELETE FROM #{quote_table_name(table)}", "Fixture Delete" }
335
+ def get_database_version # :nodoc:
336
+ SQLite3Adapter::Version.new(query_value("SELECT sqlite_version(*)"))
337
+ end
381
338
 
382
- fixture_set.each do |table_name, rows|
383
- rows.each { |row| insert_fixture(row, table_name) }
384
- end
385
- end
339
+ def check_version # :nodoc:
340
+ if database_version < "3.8.0"
341
+ raise "Your version of SQLite (#{database_version}) is too old. Active Record supports SQLite >= 3.8."
386
342
  end
387
343
  end
388
344
 
389
345
  private
346
+ # See https://www.sqlite.org/limits.html,
347
+ # the default value is 999 when not configured.
348
+ def bind_params_length
349
+ 999
350
+ end
351
+
390
352
  def initialize_type_map(m = type_map)
391
353
  super
392
354
  register_class_with_limit m, %r(int)i, SQLite3Integer
@@ -402,17 +364,31 @@ module ActiveRecord
402
364
  # See: https://www.sqlite.org/lang_altertable.html
403
365
  # SQLite has an additional restriction on the ALTER TABLE statement
404
366
  def invalid_alter_table_type?(type, options)
405
- type.to_sym == :primary_key || options[:primary_key]
367
+ type.to_sym == :primary_key || options[:primary_key] ||
368
+ options[:null] == false && options[:default].nil?
406
369
  end
407
370
 
408
- def alter_table(table_name, options = {})
371
+ def alter_table(table_name, foreign_keys = foreign_keys(table_name), **options)
409
372
  altered_table_name = "a#{table_name}"
410
- caller = lambda { |definition| yield definition if block_given? }
373
+
374
+ caller = lambda do |definition|
375
+ rename = options[:rename] || {}
376
+ foreign_keys.each do |fk|
377
+ if column = rename[fk.options[:column]]
378
+ fk.options[:column] = column
379
+ end
380
+ to_table = strip_table_name_prefix_and_suffix(fk.to_table)
381
+ definition.foreign_key(to_table, **fk.options)
382
+ end
383
+
384
+ yield definition if block_given?
385
+ end
411
386
 
412
387
  transaction do
413
- move_table(table_name, altered_table_name,
414
- options.merge(temporary: true))
415
- move_table(altered_table_name, table_name, &caller)
388
+ disable_referential_integrity do
389
+ move_table(table_name, altered_table_name, options.merge(temporary: true))
390
+ move_table(altered_table_name, table_name, &caller)
391
+ end
416
392
  end
417
393
  end
418
394
 
@@ -424,7 +400,7 @@ module ActiveRecord
424
400
  def copy_table(from, to, options = {})
425
401
  from_primary_key = primary_key(from)
426
402
  options[:id] = false
427
- create_table(to, options) do |definition|
403
+ create_table(to, **options) do |definition|
428
404
  @definition = definition
429
405
  if from_primary_key.is_a?(Array)
430
406
  @definition.primary_keys from_primary_key
@@ -442,6 +418,7 @@ module ActiveRecord
442
418
  primary_key: column_name == from_primary_key
443
419
  )
444
420
  end
421
+
445
422
  yield @definition if block_given?
446
423
  end
447
424
  copy_table_indexes(from, to, options[:rename] || {})
@@ -459,9 +436,12 @@ module ActiveRecord
459
436
  name = name[1..-1]
460
437
  end
461
438
 
462
- to_column_names = columns(to).map(&:name)
463
- columns = index.columns.map { |c| rename[c] || c }.select do |column|
464
- to_column_names.include?(column)
439
+ columns = index.columns
440
+ if columns.is_a?(Array)
441
+ to_column_names = columns(to).map(&:name)
442
+ columns = columns.map { |c| rename[c] || c }.select do |column|
443
+ to_column_names.include?(column)
444
+ end
465
445
  end
466
446
 
467
447
  unless columns.empty?
@@ -487,22 +467,18 @@ module ActiveRecord
487
467
  SELECT #{quoted_from_columns} FROM #{quote_table_name(from)}")
488
468
  end
489
469
 
490
- def sqlite_version
491
- @sqlite_version ||= SQLite3Adapter::Version.new(query_value("SELECT sqlite_version(*)"))
492
- end
493
-
494
- def translate_exception(exception, message)
470
+ def translate_exception(exception, message:, sql:, binds:)
495
471
  case exception.message
496
472
  # SQLite 3.8.2 returns a newly formatted error message:
497
473
  # UNIQUE constraint failed: *table_name*.*column_name*
498
474
  # Older versions of SQLite return:
499
475
  # column *column_name* is not unique
500
476
  when /column(s)? .* (is|are) not unique/, /UNIQUE constraint failed: .*/
501
- RecordNotUnique.new(message)
477
+ RecordNotUnique.new(message, sql: sql, binds: binds)
502
478
  when /.* may not be NULL/, /NOT NULL constraint failed: .*/
503
- NotNullViolation.new(message)
479
+ NotNullViolation.new(message, sql: sql, binds: binds)
504
480
  when /FOREIGN KEY constraint failed/i
505
- InvalidForeignKey.new(message)
481
+ InvalidForeignKey.new(message, sql: sql, binds: binds)
506
482
  else
507
483
  super
508
484
  end
@@ -512,7 +488,7 @@ module ActiveRecord
512
488
 
513
489
  def table_structure_with_collation(table_name, basic_structure)
514
490
  collation_hash = {}
515
- sql = <<-SQL
491
+ sql = <<~SQL
516
492
  SELECT sql FROM
517
493
  (SELECT * FROM sqlite_master UNION ALL
518
494
  SELECT * FROM sqlite_temp_master)
@@ -545,7 +521,7 @@ module ActiveRecord
545
521
  column
546
522
  end
547
523
  else
548
- basic_structure.to_hash
524
+ basic_structure.to_a
549
525
  end
550
526
  end
551
527
 
@@ -553,7 +529,21 @@ module ActiveRecord
553
529
  Arel::Visitors::SQLite.new(self)
554
530
  end
555
531
 
532
+ def build_statement_pool
533
+ StatementPool.new(self.class.type_cast_config_to_integer(@config[:statement_limit]))
534
+ end
535
+
536
+ def connect
537
+ @connection = ::SQLite3::Database.new(
538
+ @config[:database].to_s,
539
+ @config.merge(results_as_hash: true)
540
+ )
541
+ configure_connection
542
+ end
543
+
556
544
  def configure_connection
545
+ @connection.busy_timeout(self.class.type_cast_config_to_integer(@config[:timeout])) if @config[:timeout]
546
+
557
547
  execute("PRAGMA foreign_keys = ON", "SCHEMA")
558
548
  end
559
549
 
@@ -48,7 +48,6 @@ module ActiveRecord
48
48
  end
49
49
 
50
50
  private
51
-
52
51
  def cache
53
52
  @cache[Process.pid]
54
53
  end