activerecord 5.1.0 → 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 (261) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +596 -450
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -5
  5. data/examples/performance.rb +2 -0
  6. data/examples/simple.rb +2 -0
  7. data/lib/active_record.rb +11 -4
  8. data/lib/active_record/aggregations.rb +6 -5
  9. data/lib/active_record/association_relation.rb +7 -5
  10. data/lib/active_record/associations.rb +77 -85
  11. data/lib/active_record/associations/alias_tracker.rb +23 -32
  12. data/lib/active_record/associations/association.rb +49 -35
  13. data/lib/active_record/associations/association_scope.rb +55 -55
  14. data/lib/active_record/associations/belongs_to_association.rb +30 -11
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
  16. data/lib/active_record/associations/builder/association.rb +4 -7
  17. data/lib/active_record/associations/builder/belongs_to.rb +21 -8
  18. data/lib/active_record/associations/builder/collection_association.rb +1 -1
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
  20. data/lib/active_record/associations/builder/has_many.rb +2 -0
  21. data/lib/active_record/associations/builder/has_one.rb +2 -0
  22. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  23. data/lib/active_record/associations/collection_association.rb +66 -53
  24. data/lib/active_record/associations/collection_proxy.rb +30 -73
  25. data/lib/active_record/associations/foreign_association.rb +2 -0
  26. data/lib/active_record/associations/has_many_association.rb +13 -2
  27. data/lib/active_record/associations/has_many_through_association.rb +37 -19
  28. data/lib/active_record/associations/has_one_association.rb +14 -1
  29. data/lib/active_record/associations/has_one_through_association.rb +13 -8
  30. data/lib/active_record/associations/join_dependency.rb +52 -96
  31. data/lib/active_record/associations/join_dependency/join_association.rb +22 -75
  32. data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
  33. data/lib/active_record/associations/join_dependency/join_part.rb +9 -9
  34. data/lib/active_record/associations/preloader.rb +17 -37
  35. data/lib/active_record/associations/preloader/association.rb +53 -92
  36. data/lib/active_record/associations/preloader/through_association.rb +72 -73
  37. data/lib/active_record/associations/singular_association.rb +14 -16
  38. data/lib/active_record/associations/through_association.rb +27 -12
  39. data/lib/active_record/attribute_assignment.rb +2 -5
  40. data/lib/active_record/attribute_decorators.rb +3 -2
  41. data/lib/active_record/attribute_methods.rb +65 -24
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
  43. data/lib/active_record/attribute_methods/dirty.rb +33 -216
  44. data/lib/active_record/attribute_methods/primary_key.rb +10 -13
  45. data/lib/active_record/attribute_methods/query.rb +2 -0
  46. data/lib/active_record/attribute_methods/read.rb +9 -3
  47. data/lib/active_record/attribute_methods/serialization.rb +23 -0
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
  49. data/lib/active_record/attribute_methods/write.rb +22 -19
  50. data/lib/active_record/attributes.rb +7 -6
  51. data/lib/active_record/autosave_association.rb +15 -13
  52. data/lib/active_record/base.rb +2 -0
  53. data/lib/active_record/callbacks.rb +12 -6
  54. data/lib/active_record/coders/json.rb +2 -0
  55. data/lib/active_record/coders/yaml_column.rb +2 -0
  56. data/lib/active_record/collection_cache_key.rb +15 -11
  57. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +120 -39
  58. data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -0
  59. data/lib/active_record/connection_adapters/abstract/database_statements.rb +192 -37
  60. data/lib/active_record/connection_adapters/abstract/query_cache.rb +13 -2
  61. data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -25
  62. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -6
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +65 -7
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +158 -87
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -21
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +86 -98
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +126 -189
  70. data/lib/active_record/connection_adapters/column.rb +4 -2
  71. data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
  72. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +13 -2
  73. data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
  74. data/lib/active_record/connection_adapters/mysql/database_statements.rb +45 -15
  75. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
  76. data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
  77. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
  78. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -10
  79. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -23
  80. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +106 -1
  81. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
  82. data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
  83. data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
  84. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -32
  85. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid.rb +3 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +13 -1
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -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 +2 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  95. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  99. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
  101. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +8 -2
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  109. data/lib/active_record/connection_adapters/postgresql/quoting.rb +22 -1
  110. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
  111. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +50 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
  113. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
  114. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +258 -129
  115. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
  116. data/lib/active_record/connection_adapters/postgresql/utils.rb +3 -1
  117. data/lib/active_record/connection_adapters/postgresql_adapter.rb +75 -87
  118. data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
  119. data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
  120. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
  121. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +24 -1
  122. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
  124. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
  125. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +75 -1
  126. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +90 -96
  127. data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
  128. data/lib/active_record/connection_handling.rb +4 -2
  129. data/lib/active_record/core.rb +41 -61
  130. data/lib/active_record/counter_cache.rb +20 -15
  131. data/lib/active_record/define_callbacks.rb +5 -3
  132. data/lib/active_record/dynamic_matchers.rb +9 -9
  133. data/lib/active_record/enum.rb +18 -13
  134. data/lib/active_record/errors.rb +60 -15
  135. data/lib/active_record/explain.rb +3 -1
  136. data/lib/active_record/explain_registry.rb +2 -0
  137. data/lib/active_record/explain_subscriber.rb +2 -0
  138. data/lib/active_record/fixture_set/file.rb +2 -0
  139. data/lib/active_record/fixtures.rb +67 -60
  140. data/lib/active_record/gem_version.rb +4 -2
  141. data/lib/active_record/inheritance.rb +49 -19
  142. data/lib/active_record/integration.rb +58 -19
  143. data/lib/active_record/internal_metadata.rb +2 -0
  144. data/lib/active_record/legacy_yaml_adapter.rb +3 -1
  145. data/lib/active_record/locking/optimistic.rb +30 -42
  146. data/lib/active_record/locking/pessimistic.rb +10 -7
  147. data/lib/active_record/log_subscriber.rb +46 -4
  148. data/lib/active_record/migration.rb +189 -139
  149. data/lib/active_record/migration/command_recorder.rb +11 -9
  150. data/lib/active_record/migration/compatibility.rb +81 -29
  151. data/lib/active_record/migration/join_table.rb +2 -0
  152. data/lib/active_record/model_schema.rb +74 -58
  153. data/lib/active_record/nested_attributes.rb +18 -6
  154. data/lib/active_record/no_touching.rb +3 -1
  155. data/lib/active_record/null_relation.rb +2 -0
  156. data/lib/active_record/persistence.rb +199 -54
  157. data/lib/active_record/query_cache.rb +8 -10
  158. data/lib/active_record/querying.rb +5 -3
  159. data/lib/active_record/railtie.rb +62 -6
  160. data/lib/active_record/railties/console_sandbox.rb +2 -0
  161. data/lib/active_record/railties/controller_runtime.rb +2 -0
  162. data/lib/active_record/railties/databases.rake +48 -38
  163. data/lib/active_record/readonly_attributes.rb +3 -2
  164. data/lib/active_record/reflection.rb +137 -207
  165. data/lib/active_record/relation.rb +132 -207
  166. data/lib/active_record/relation/batches.rb +32 -17
  167. data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
  168. data/lib/active_record/relation/calculations.rb +66 -25
  169. data/lib/active_record/relation/delegation.rb +45 -29
  170. data/lib/active_record/relation/finder_methods.rb +76 -85
  171. data/lib/active_record/relation/from_clause.rb +2 -8
  172. data/lib/active_record/relation/merger.rb +53 -23
  173. data/lib/active_record/relation/predicate_builder.rb +60 -79
  174. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
  175. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  176. data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
  177. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
  178. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
  179. data/lib/active_record/relation/predicate_builder/range_handler.rb +26 -9
  180. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  181. data/lib/active_record/relation/query_attribute.rb +28 -2
  182. data/lib/active_record/relation/query_methods.rb +135 -103
  183. data/lib/active_record/relation/record_fetch_warning.rb +2 -0
  184. data/lib/active_record/relation/spawn_methods.rb +4 -2
  185. data/lib/active_record/relation/where_clause.rb +65 -67
  186. data/lib/active_record/relation/where_clause_factory.rb +5 -48
  187. data/lib/active_record/result.rb +2 -0
  188. data/lib/active_record/runtime_registry.rb +2 -0
  189. data/lib/active_record/sanitization.rb +129 -121
  190. data/lib/active_record/schema.rb +4 -2
  191. data/lib/active_record/schema_dumper.rb +36 -26
  192. data/lib/active_record/schema_migration.rb +2 -0
  193. data/lib/active_record/scoping.rb +12 -10
  194. data/lib/active_record/scoping/default.rb +10 -7
  195. data/lib/active_record/scoping/named.rb +40 -12
  196. data/lib/active_record/secure_token.rb +2 -0
  197. data/lib/active_record/serialization.rb +2 -0
  198. data/lib/active_record/statement_cache.rb +22 -12
  199. data/lib/active_record/store.rb +3 -1
  200. data/lib/active_record/suppressor.rb +2 -0
  201. data/lib/active_record/table_metadata.rb +12 -3
  202. data/lib/active_record/tasks/database_tasks.rb +38 -26
  203. data/lib/active_record/tasks/mysql_database_tasks.rb +11 -50
  204. data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -3
  205. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
  206. data/lib/active_record/timestamp.rb +13 -6
  207. data/lib/active_record/touch_later.rb +2 -0
  208. data/lib/active_record/transactions.rb +32 -27
  209. data/lib/active_record/translation.rb +2 -0
  210. data/lib/active_record/type.rb +4 -1
  211. data/lib/active_record/type/adapter_specific_registry.rb +2 -0
  212. data/lib/active_record/type/date.rb +2 -0
  213. data/lib/active_record/type/date_time.rb +2 -0
  214. data/lib/active_record/type/decimal_without_scale.rb +2 -0
  215. data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
  216. data/lib/active_record/type/internal/timezone.rb +2 -0
  217. data/lib/active_record/type/json.rb +30 -0
  218. data/lib/active_record/type/serialized.rb +6 -0
  219. data/lib/active_record/type/text.rb +2 -0
  220. data/lib/active_record/type/time.rb +2 -0
  221. data/lib/active_record/type/type_map.rb +2 -0
  222. data/lib/active_record/type/unsigned_integer.rb +2 -0
  223. data/lib/active_record/type_caster.rb +2 -0
  224. data/lib/active_record/type_caster/connection.rb +2 -0
  225. data/lib/active_record/type_caster/map.rb +3 -1
  226. data/lib/active_record/validations.rb +2 -0
  227. data/lib/active_record/validations/absence.rb +2 -0
  228. data/lib/active_record/validations/associated.rb +2 -0
  229. data/lib/active_record/validations/length.rb +2 -0
  230. data/lib/active_record/validations/presence.rb +2 -0
  231. data/lib/active_record/validations/uniqueness.rb +36 -6
  232. data/lib/active_record/version.rb +2 -0
  233. data/lib/rails/generators/active_record.rb +3 -1
  234. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  235. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  236. data/lib/rails/generators/active_record/migration.rb +2 -0
  237. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
  238. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
  239. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
  240. data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
  241. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
  242. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  243. metadata +24 -36
  244. data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
  245. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  246. data/lib/active_record/associations/preloader/has_many.rb +0 -15
  247. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  248. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  249. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  250. data/lib/active_record/associations/preloader/singular_association.rb +0 -18
  251. data/lib/active_record/attribute.rb +0 -240
  252. data/lib/active_record/attribute/user_provided_default.rb +0 -30
  253. data/lib/active_record/attribute_mutation_tracker.rb +0 -113
  254. data/lib/active_record/attribute_set.rb +0 -113
  255. data/lib/active_record/attribute_set/builder.rb +0 -124
  256. data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
  257. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
  258. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  259. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  260. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
  261. data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module SQLite3
@@ -1,27 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module SQLite3
4
- module ColumnMethods
5
- def primary_key(name, type = :primary_key, **options)
6
- if %i(integer bigint).include?(type) && (options.delete(:auto_increment) == true || !options.key?(:default))
7
- type = :primary_key
8
- end
9
-
10
- super
11
- end
12
- end
13
-
14
6
  class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
15
- include ColumnMethods
16
-
17
7
  def references(*args, **options)
18
8
  super(*args, type: :integer, **options)
19
9
  end
20
10
  alias :belongs_to :references
21
- end
22
11
 
23
- class Table < ActiveRecord::ConnectionAdapters::Table
24
- include ColumnMethods
12
+ private
13
+ def integer_like_primary_key_type(type, options)
14
+ :primary_key
15
+ end
25
16
  end
26
17
  end
27
18
  end
@@ -1,9 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module SQLite3
4
- module ColumnDumper # :nodoc:
6
+ class SchemaDumper < ConnectionAdapters::SchemaDumper # :nodoc:
5
7
  private
6
-
7
8
  def default_primary_key?(column)
8
9
  schema_type(column) == :integer
9
10
  end
@@ -1,13 +1,87 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  module SQLite3
4
6
  module SchemaStatements # :nodoc:
7
+ # Returns an array of indexes for the given table.
8
+ def indexes(table_name)
9
+ exec_query("PRAGMA index_list(#{quote_table_name(table_name)})", "SCHEMA").map do |row|
10
+ # Indexes SQLite creates implicitly for internal use start with "sqlite_".
11
+ # See https://www.sqlite.org/fileformat2.html#intschema
12
+ next if row["name"].starts_with?("sqlite_")
13
+
14
+ index_sql = query_value(<<-SQL, "SCHEMA")
15
+ SELECT sql
16
+ FROM sqlite_master
17
+ WHERE name = #{quote(row['name'])} AND type = 'index'
18
+ UNION ALL
19
+ SELECT sql
20
+ FROM sqlite_temp_master
21
+ WHERE name = #{quote(row['name'])} AND type = 'index'
22
+ SQL
23
+
24
+ /\sWHERE\s+(?<where>.+)$/i =~ index_sql
25
+
26
+ columns = exec_query("PRAGMA index_info(#{quote(row['name'])})", "SCHEMA").map do |col|
27
+ col["name"]
28
+ end
29
+
30
+ # Add info on sort order for columns (only desc order is explicitly specified, asc is
31
+ # the default)
32
+ orders = {}
33
+ if index_sql # index_sql can be null in case of primary key indexes
34
+ index_sql.scan(/"(\w+)" DESC/).flatten.each { |order_column|
35
+ orders[order_column] = :desc
36
+ }
37
+ end
38
+
39
+ IndexDefinition.new(
40
+ table_name,
41
+ row["name"],
42
+ row["unique"] != 0,
43
+ columns,
44
+ where: where,
45
+ orders: orders
46
+ )
47
+ end.compact
48
+ end
49
+
50
+ def create_schema_dumper(options)
51
+ SQLite3::SchemaDumper.create(self, options)
52
+ end
53
+
5
54
  private
55
+ def schema_creation
56
+ SQLite3::SchemaCreation.new(self)
57
+ end
58
+
59
+ def create_table_definition(*args)
60
+ SQLite3::TableDefinition.new(*args)
61
+ end
62
+
63
+ def new_column_from_field(table_name, field)
64
+ default = \
65
+ case field["dflt_value"]
66
+ when /^null$/i
67
+ nil
68
+ when /^'(.*)'$/m
69
+ $1.gsub("''", "'")
70
+ when /^"(.*)"$/m
71
+ $1.gsub('""', '"')
72
+ else
73
+ field["dflt_value"]
74
+ end
75
+
76
+ type_metadata = fetch_type_metadata(field["type"])
77
+ Column.new(field["name"], default, type_metadata, field["notnull"].to_i == 0, table_name, nil, field["collation"])
78
+ end
79
+
6
80
  def data_source_sql(name = nil, type: nil)
7
81
  scope = quoted_scope(name, type: type)
8
82
  scope[:type] ||= "'table','view'"
9
83
 
10
- sql = "SELECT name FROM sqlite_master WHERE name <> 'sqlite_sequence'"
84
+ sql = "SELECT name FROM sqlite_master WHERE name <> 'sqlite_sequence'".dup
11
85
  sql << " AND name = #{scope[:name]}" if scope[:name]
12
86
  sql << " AND type IN (#{scope[:type]})"
13
87
  sql
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_record/connection_adapters/abstract_adapter"
2
4
  require "active_record/connection_adapters/statement_pool"
3
5
  require "active_record/connection_adapters/sqlite3/explain_pretty_printer"
@@ -7,7 +9,7 @@ require "active_record/connection_adapters/sqlite3/schema_definitions"
7
9
  require "active_record/connection_adapters/sqlite3/schema_dumper"
8
10
  require "active_record/connection_adapters/sqlite3/schema_statements"
9
11
 
10
- gem "sqlite3", "~> 1.3.6"
12
+ gem "sqlite3", "~> 1.3", ">= 1.3.6"
11
13
  require "sqlite3"
12
14
 
13
15
  module ActiveRecord
@@ -55,11 +57,10 @@ module ActiveRecord
55
57
  ADAPTER_NAME = "SQLite".freeze
56
58
 
57
59
  include SQLite3::Quoting
58
- include SQLite3::ColumnDumper
59
60
  include SQLite3::SchemaStatements
60
61
 
61
62
  NATIVE_DATABASE_TYPES = {
62
- primary_key: "INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL",
63
+ primary_key: "integer PRIMARY KEY AUTOINCREMENT NOT NULL",
63
64
  string: { name: "varchar" },
64
65
  text: { name: "text" },
65
66
  integer: { name: "integer" },
@@ -69,33 +70,38 @@ module ActiveRecord
69
70
  time: { name: "time" },
70
71
  date: { name: "date" },
71
72
  binary: { name: "blob" },
72
- boolean: { name: "boolean" }
73
+ boolean: { name: "boolean" },
74
+ json: { name: "json" },
73
75
  }
74
76
 
75
- class StatementPool < ConnectionAdapters::StatementPool
76
- private
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
77
93
 
94
+ class StatementPool < ConnectionAdapters::StatementPool # :nodoc:
95
+ private
78
96
  def dealloc(stmt)
79
97
  stmt[:stmt].close unless stmt[:stmt].closed?
80
98
  end
81
99
  end
82
100
 
83
- def update_table_definition(table_name, base) # :nodoc:
84
- SQLite3::Table.new(table_name, base)
85
- end
86
-
87
- def schema_creation # :nodoc:
88
- SQLite3::SchemaCreation.new self
89
- end
90
-
91
- def arel_visitor # :nodoc:
92
- Arel::Visitors::SQLite.new(self)
93
- end
94
-
95
101
  def initialize(connection, logger, connection_options, config)
96
102
  super(connection, logger, config)
97
103
 
98
- @active = nil
104
+ @active = true
99
105
  @statements = StatementPool.new(self.class.type_cast_config_to_integer(config[:statement_limit]))
100
106
 
101
107
  configure_connection
@@ -113,12 +119,6 @@ module ActiveRecord
113
119
  sqlite_version >= "3.8.0"
114
120
  end
115
121
 
116
- # Returns true, since this connection adapter supports prepared statement
117
- # caching.
118
- def supports_statement_cache?
119
- true
120
- end
121
-
122
122
  def requires_reloading?
123
123
  true
124
124
  end
@@ -135,12 +135,16 @@ module ActiveRecord
135
135
  true
136
136
  end
137
137
 
138
+ def supports_json?
139
+ true
140
+ end
141
+
138
142
  def supports_multi_insert?
139
143
  sqlite_version >= "3.7.11"
140
144
  end
141
145
 
142
146
  def active?
143
- @active != false
147
+ @active
144
148
  end
145
149
 
146
150
  # Disconnects from the database if already connected. Otherwise, this
@@ -183,7 +187,7 @@ module ActiveRecord
183
187
  # REFERENTIAL INTEGRITY ====================================
184
188
 
185
189
  def disable_referential_integrity # :nodoc:
186
- old = select_value("PRAGMA foreign_keys")
190
+ old = query_value("PRAGMA foreign_keys")
187
191
 
188
192
  begin
189
193
  execute("PRAGMA foreign_keys = OFF")
@@ -267,53 +271,6 @@ module ActiveRecord
267
271
 
268
272
  # SCHEMA STATEMENTS ========================================
269
273
 
270
- def new_column_from_field(table_name, field) # :nondoc:
271
- case field["dflt_value"]
272
- when /^null$/i
273
- field["dflt_value"] = nil
274
- when /^'(.*)'$/m
275
- field["dflt_value"] = $1.gsub("''", "'")
276
- when /^"(.*)"$/m
277
- field["dflt_value"] = $1.gsub('""', '"')
278
- end
279
-
280
- collation = field["collation"]
281
- sql_type = field["type"]
282
- type_metadata = fetch_type_metadata(sql_type)
283
- new_column(field["name"], field["dflt_value"], type_metadata, field["notnull"].to_i == 0, table_name, nil, collation)
284
- end
285
-
286
- # Returns an array of indexes for the given table.
287
- def indexes(table_name, name = nil) #:nodoc:
288
- if name
289
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
290
- Passing name to #indexes is deprecated without replacement.
291
- MSG
292
- end
293
-
294
- exec_query("PRAGMA index_list(#{quote_table_name(table_name)})", "SCHEMA").map do |row|
295
- sql = <<-SQL
296
- SELECT sql
297
- FROM sqlite_master
298
- WHERE name=#{quote(row['name'])} AND type='index'
299
- UNION ALL
300
- SELECT sql
301
- FROM sqlite_temp_master
302
- WHERE name=#{quote(row['name'])} AND type='index'
303
- SQL
304
- index_sql = exec_query(sql).first["sql"]
305
- match = /\sWHERE\s+(.+)$/i.match(index_sql)
306
- where = match[1] if match
307
- IndexDefinition.new(
308
- table_name,
309
- row["name"],
310
- row["unique"] != 0,
311
- exec_query("PRAGMA index_info('#{row['name']}')", "SCHEMA").map { |col|
312
- col["name"]
313
- }, nil, nil, where)
314
- end
315
- end
316
-
317
274
  def primary_keys(table_name) # :nodoc:
318
275
  pks = table_structure(table_name).select { |f| f["pk"] > 0 }
319
276
  pks.sort_by { |f| f["pk"] }.map { |f| f["name"] }
@@ -333,19 +290,18 @@ module ActiveRecord
333
290
  rename_table_indexes(table_name, new_name)
334
291
  end
335
292
 
336
- # See: http://www.sqlite.org/lang_altertable.html
337
- # SQLite has an additional restriction on the ALTER TABLE statement
338
- def valid_alter_table_type?(type)
339
- type.to_sym != :primary_key
293
+ def valid_alter_table_type?(type, options = {})
294
+ !invalid_alter_table_type?(type, options)
340
295
  end
296
+ deprecate :valid_alter_table_type?
341
297
 
342
298
  def add_column(table_name, column_name, type, options = {}) #:nodoc:
343
- if valid_alter_table_type?(type)
344
- super(table_name, column_name, type, options)
345
- else
299
+ if invalid_alter_table_type?(type, options)
346
300
  alter_table(table_name) do |definition|
347
301
  definition.column(column_name, type, options)
348
302
  end
303
+ else
304
+ super
349
305
  end
350
306
  end
351
307
 
@@ -398,7 +354,7 @@ module ActiveRecord
398
354
  alias :add_belongs_to :add_reference
399
355
 
400
356
  def foreign_keys(table_name)
401
- fk_info = select_all("PRAGMA foreign_key_list(#{quote(table_name)})", "SCHEMA")
357
+ fk_info = exec_query("PRAGMA foreign_key_list(#{quote(table_name)})", "SCHEMA")
402
358
  fk_info.map do |row|
403
359
  options = {
404
360
  column: row["from"],
@@ -410,7 +366,31 @@ module ActiveRecord
410
366
  end
411
367
  end
412
368
 
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)
375
+ end
376
+
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" }
381
+
382
+ fixture_set.each do |table_name, rows|
383
+ rows.each { |row| insert_fixture(row, table_name) }
384
+ end
385
+ end
386
+ end
387
+ end
388
+
413
389
  private
390
+ def initialize_type_map(m = type_map)
391
+ super
392
+ register_class_with_limit m, %r(int)i, SQLite3Integer
393
+ end
414
394
 
415
395
  def table_structure(table_name)
416
396
  structure = exec_query("PRAGMA table_info(#{quote_table_name(table_name)})", "SCHEMA")
@@ -419,6 +399,12 @@ module ActiveRecord
419
399
  end
420
400
  alias column_definitions table_structure
421
401
 
402
+ # See: https://www.sqlite.org/lang_altertable.html
403
+ # SQLite has an additional restriction on the ALTER TABLE statement
404
+ def invalid_alter_table_type?(type, options)
405
+ type.to_sym == :primary_key || options[:primary_key]
406
+ end
407
+
422
408
  def alter_table(table_name, options = {})
423
409
  altered_table_name = "a#{table_name}"
424
410
  caller = lambda { |definition| yield definition if block_given? }
@@ -440,18 +426,21 @@ module ActiveRecord
440
426
  options[:id] = false
441
427
  create_table(to, options) do |definition|
442
428
  @definition = definition
443
- @definition.primary_key(from_primary_key) if from_primary_key.present?
429
+ if from_primary_key.is_a?(Array)
430
+ @definition.primary_keys from_primary_key
431
+ end
444
432
  columns(from).each do |column|
445
433
  column_name = options[:rename] ?
446
434
  (options[:rename][column.name] ||
447
435
  options[:rename][column.name.to_sym] ||
448
436
  column.name) : column.name
449
- next if column_name == from_primary_key
450
437
 
451
438
  @definition.column(column_name, column.type,
452
439
  limit: column.limit, default: column.default,
453
440
  precision: column.precision, scale: column.scale,
454
- null: column.null, collation: column.collation)
441
+ null: column.null, collation: column.collation,
442
+ primary_key: column_name == from_primary_key
443
+ )
455
444
  end
456
445
  yield @definition if block_given?
457
446
  end
@@ -479,6 +468,7 @@ module ActiveRecord
479
468
  # index name can't be the same
480
469
  opts = { name: name.gsub(/(^|_)(#{from})_/, "\\1#{to}_"), internal: true }
481
470
  opts[:unique] = true if index.unique
471
+ opts[:where] = index.where if index.where
482
472
  add_index(to, columns, opts)
483
473
  end
484
474
  end
@@ -498,7 +488,7 @@ module ActiveRecord
498
488
  end
499
489
 
500
490
  def sqlite_version
501
- @sqlite_version ||= SQLite3Adapter::Version.new(select_value("SELECT sqlite_version(*)"))
491
+ @sqlite_version ||= SQLite3Adapter::Version.new(query_value("SELECT sqlite_version(*)"))
502
492
  end
503
493
 
504
494
  def translate_exception(exception, message)
@@ -559,21 +549,25 @@ module ActiveRecord
559
549
  end
560
550
  end
561
551
 
562
- def create_table_definition(*args)
563
- SQLite3::TableDefinition.new(*args)
564
- end
565
-
566
- def extract_foreign_key_action(specifier)
567
- case specifier
568
- when "CASCADE"; :cascade
569
- when "SET NULL"; :nullify
570
- when "RESTRICT"; :restrict
571
- end
552
+ def arel_visitor
553
+ Arel::Visitors::SQLite.new(self)
572
554
  end
573
555
 
574
556
  def configure_connection
575
557
  execute("PRAGMA foreign_keys = ON", "SCHEMA")
576
558
  end
559
+
560
+ class SQLite3Integer < Type::Integer # :nodoc:
561
+ private
562
+ def _limit
563
+ # INTEGER storage class can be stored 8 bytes value.
564
+ # See https://www.sqlite.org/datatype3.html#storage_classes_and_datatypes
565
+ limit || 8
566
+ end
567
+ end
568
+
569
+ ActiveRecord::Type.register(:integer, SQLite3Integer, adapter: :sqlite3)
577
570
  end
571
+ ActiveSupport.run_load_hooks(:active_record_sqlite3adapter, SQLite3Adapter)
578
572
  end
579
573
  end