activerecord 6.0.0 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (268) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +872 -582
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +3 -3
  5. data/lib/active_record.rb +7 -13
  6. data/lib/active_record/aggregations.rb +1 -2
  7. data/lib/active_record/association_relation.rb +22 -12
  8. data/lib/active_record/associations.rb +116 -13
  9. data/lib/active_record/associations/alias_tracker.rb +19 -16
  10. data/lib/active_record/associations/association.rb +49 -29
  11. data/lib/active_record/associations/association_scope.rb +17 -15
  12. data/lib/active_record/associations/belongs_to_association.rb +15 -5
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
  14. data/lib/active_record/associations/builder/association.rb +9 -3
  15. data/lib/active_record/associations/builder/belongs_to.rb +10 -7
  16. data/lib/active_record/associations/builder/collection_association.rb +5 -4
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -3
  18. data/lib/active_record/associations/builder/has_many.rb +6 -2
  19. data/lib/active_record/associations/builder/has_one.rb +11 -14
  20. data/lib/active_record/associations/builder/singular_association.rb +1 -1
  21. data/lib/active_record/associations/collection_association.rb +25 -8
  22. data/lib/active_record/associations/collection_proxy.rb +14 -7
  23. data/lib/active_record/associations/foreign_association.rb +13 -0
  24. data/lib/active_record/associations/has_many_association.rb +24 -3
  25. data/lib/active_record/associations/has_many_through_association.rb +10 -4
  26. data/lib/active_record/associations/has_one_association.rb +15 -1
  27. data/lib/active_record/associations/join_dependency.rb +77 -42
  28. data/lib/active_record/associations/join_dependency/join_association.rb +36 -14
  29. data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
  30. data/lib/active_record/associations/preloader.rb +13 -8
  31. data/lib/active_record/associations/preloader/association.rb +51 -25
  32. data/lib/active_record/associations/preloader/through_association.rb +2 -2
  33. data/lib/active_record/associations/singular_association.rb +1 -1
  34. data/lib/active_record/associations/through_association.rb +1 -1
  35. data/lib/active_record/attribute_assignment.rb +10 -9
  36. data/lib/active_record/attribute_methods.rb +64 -54
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -10
  38. data/lib/active_record/attribute_methods/dirty.rb +3 -13
  39. data/lib/active_record/attribute_methods/primary_key.rb +6 -4
  40. data/lib/active_record/attribute_methods/query.rb +3 -6
  41. data/lib/active_record/attribute_methods/read.rb +8 -12
  42. data/lib/active_record/attribute_methods/serialization.rb +11 -6
  43. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
  44. data/lib/active_record/attribute_methods/write.rb +12 -21
  45. data/lib/active_record/attributes.rb +32 -8
  46. data/lib/active_record/autosave_association.rb +63 -44
  47. data/lib/active_record/base.rb +2 -14
  48. data/lib/active_record/callbacks.rb +153 -24
  49. data/lib/active_record/coders/yaml_column.rb +1 -2
  50. data/lib/active_record/connection_adapters.rb +50 -0
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +202 -138
  52. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
  53. data/lib/active_record/connection_adapters/abstract/database_statements.rb +86 -37
  54. data/lib/active_record/connection_adapters/abstract/query_cache.rb +4 -9
  55. data/lib/active_record/connection_adapters/abstract/quoting.rb +34 -34
  56. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  57. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +152 -116
  58. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +137 -52
  59. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
  60. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +263 -107
  61. data/lib/active_record/connection_adapters/abstract/transaction.rb +82 -35
  62. data/lib/active_record/connection_adapters/abstract_adapter.rb +74 -76
  63. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +149 -115
  64. data/lib/active_record/connection_adapters/column.rb +15 -1
  65. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  66. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
  67. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  68. data/lib/active_record/connection_adapters/mysql/database_statements.rb +30 -36
  69. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  70. data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
  71. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -7
  72. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
  73. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
  74. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +17 -13
  75. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  76. data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -13
  77. data/lib/active_record/connection_adapters/pool_config.rb +63 -0
  78. data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
  79. data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
  80. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +21 -56
  81. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  82. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
  83. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  84. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +0 -1
  88. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
  90. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
  93. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -6
  94. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  95. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -2
  96. data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
  97. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
  98. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +7 -3
  99. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
  100. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  101. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +72 -54
  102. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  103. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  104. data/lib/active_record/connection_adapters/postgresql_adapter.rb +81 -57
  105. data/lib/active_record/connection_adapters/schema_cache.rb +98 -15
  106. data/lib/active_record/connection_adapters/sql_type_metadata.rb +10 -0
  107. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +38 -12
  108. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -2
  109. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  110. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +38 -5
  111. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -57
  112. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  113. data/lib/active_record/connection_handling.rb +211 -81
  114. data/lib/active_record/core.rb +237 -69
  115. data/lib/active_record/counter_cache.rb +4 -1
  116. data/lib/active_record/database_configurations.rb +124 -85
  117. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  118. data/lib/active_record/database_configurations/database_config.rb +52 -9
  119. data/lib/active_record/database_configurations/hash_config.rb +54 -8
  120. data/lib/active_record/database_configurations/url_config.rb +15 -41
  121. data/lib/active_record/delegated_type.rb +209 -0
  122. data/lib/active_record/destroy_association_async_job.rb +36 -0
  123. data/lib/active_record/dynamic_matchers.rb +2 -3
  124. data/lib/active_record/enum.rb +40 -16
  125. data/lib/active_record/errors.rb +47 -12
  126. data/lib/active_record/explain.rb +9 -5
  127. data/lib/active_record/explain_subscriber.rb +1 -1
  128. data/lib/active_record/fixture_set/file.rb +10 -17
  129. data/lib/active_record/fixture_set/model_metadata.rb +1 -2
  130. data/lib/active_record/fixture_set/render_context.rb +1 -1
  131. data/lib/active_record/fixture_set/table_row.rb +2 -3
  132. data/lib/active_record/fixture_set/table_rows.rb +0 -1
  133. data/lib/active_record/fixtures.rb +54 -11
  134. data/lib/active_record/gem_version.rb +1 -1
  135. data/lib/active_record/inheritance.rb +40 -21
  136. data/lib/active_record/insert_all.rb +39 -10
  137. data/lib/active_record/integration.rb +3 -5
  138. data/lib/active_record/internal_metadata.rb +16 -7
  139. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  140. data/lib/active_record/locking/optimistic.rb +22 -17
  141. data/lib/active_record/locking/pessimistic.rb +6 -2
  142. data/lib/active_record/log_subscriber.rb +27 -9
  143. data/lib/active_record/middleware/database_selector.rb +4 -2
  144. data/lib/active_record/middleware/database_selector/resolver.rb +14 -14
  145. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  146. data/lib/active_record/migration.rb +114 -84
  147. data/lib/active_record/migration/command_recorder.rb +53 -45
  148. data/lib/active_record/migration/compatibility.rb +70 -20
  149. data/lib/active_record/migration/join_table.rb +0 -1
  150. data/lib/active_record/model_schema.rb +120 -15
  151. data/lib/active_record/nested_attributes.rb +2 -5
  152. data/lib/active_record/no_touching.rb +1 -1
  153. data/lib/active_record/null_relation.rb +0 -1
  154. data/lib/active_record/persistence.rb +50 -46
  155. data/lib/active_record/query_cache.rb +15 -5
  156. data/lib/active_record/querying.rb +12 -7
  157. data/lib/active_record/railtie.rb +65 -45
  158. data/lib/active_record/railties/databases.rake +267 -93
  159. data/lib/active_record/readonly_attributes.rb +4 -0
  160. data/lib/active_record/reflection.rb +77 -63
  161. data/lib/active_record/relation.rb +108 -67
  162. data/lib/active_record/relation/batches.rb +38 -32
  163. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  164. data/lib/active_record/relation/calculations.rb +102 -45
  165. data/lib/active_record/relation/delegation.rb +9 -7
  166. data/lib/active_record/relation/finder_methods.rb +55 -17
  167. data/lib/active_record/relation/from_clause.rb +5 -1
  168. data/lib/active_record/relation/merger.rb +27 -26
  169. data/lib/active_record/relation/predicate_builder.rb +55 -35
  170. data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
  171. data/lib/active_record/relation/predicate_builder/association_query_value.rb +4 -5
  172. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +3 -3
  173. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  174. data/lib/active_record/relation/query_methods.rb +340 -180
  175. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  176. data/lib/active_record/relation/spawn_methods.rb +8 -8
  177. data/lib/active_record/relation/where_clause.rb +104 -58
  178. data/lib/active_record/result.rb +41 -34
  179. data/lib/active_record/runtime_registry.rb +2 -2
  180. data/lib/active_record/sanitization.rb +6 -17
  181. data/lib/active_record/schema_dumper.rb +34 -4
  182. data/lib/active_record/schema_migration.rb +2 -8
  183. data/lib/active_record/scoping.rb +0 -1
  184. data/lib/active_record/scoping/default.rb +0 -1
  185. data/lib/active_record/scoping/named.rb +7 -18
  186. data/lib/active_record/secure_token.rb +16 -8
  187. data/lib/active_record/serialization.rb +5 -3
  188. data/lib/active_record/signed_id.rb +116 -0
  189. data/lib/active_record/statement_cache.rb +20 -4
  190. data/lib/active_record/store.rb +3 -3
  191. data/lib/active_record/suppressor.rb +2 -2
  192. data/lib/active_record/table_metadata.rb +39 -36
  193. data/lib/active_record/tasks/database_tasks.rb +139 -113
  194. data/lib/active_record/tasks/mysql_database_tasks.rb +34 -36
  195. data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -27
  196. data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -10
  197. data/lib/active_record/test_databases.rb +5 -4
  198. data/lib/active_record/test_fixtures.rb +38 -16
  199. data/lib/active_record/timestamp.rb +4 -7
  200. data/lib/active_record/touch_later.rb +20 -21
  201. data/lib/active_record/transactions.rb +22 -71
  202. data/lib/active_record/type.rb +8 -2
  203. data/lib/active_record/type/adapter_specific_registry.rb +2 -5
  204. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  205. data/lib/active_record/type/serialized.rb +6 -3
  206. data/lib/active_record/type/time.rb +10 -0
  207. data/lib/active_record/type/type_map.rb +0 -1
  208. data/lib/active_record/type/unsigned_integer.rb +0 -1
  209. data/lib/active_record/type_caster/connection.rb +0 -1
  210. data/lib/active_record/type_caster/map.rb +8 -5
  211. data/lib/active_record/validations.rb +3 -3
  212. data/lib/active_record/validations/associated.rb +1 -2
  213. data/lib/active_record/validations/numericality.rb +35 -0
  214. data/lib/active_record/validations/uniqueness.rb +24 -4
  215. data/lib/arel.rb +15 -12
  216. data/lib/arel/attributes/attribute.rb +4 -0
  217. data/lib/arel/collectors/bind.rb +5 -0
  218. data/lib/arel/collectors/composite.rb +8 -0
  219. data/lib/arel/collectors/sql_string.rb +7 -0
  220. data/lib/arel/collectors/substitute_binds.rb +7 -0
  221. data/lib/arel/nodes.rb +3 -1
  222. data/lib/arel/nodes/binary.rb +82 -8
  223. data/lib/arel/nodes/bind_param.rb +8 -0
  224. data/lib/arel/nodes/casted.rb +21 -9
  225. data/lib/arel/nodes/equality.rb +6 -9
  226. data/lib/arel/nodes/grouping.rb +3 -0
  227. data/lib/arel/nodes/homogeneous_in.rb +72 -0
  228. data/lib/arel/nodes/in.rb +8 -1
  229. data/lib/arel/nodes/infix_operation.rb +13 -1
  230. data/lib/arel/nodes/join_source.rb +1 -1
  231. data/lib/arel/nodes/node.rb +7 -6
  232. data/lib/arel/nodes/ordering.rb +27 -0
  233. data/lib/arel/nodes/sql_literal.rb +3 -0
  234. data/lib/arel/nodes/table_alias.rb +7 -3
  235. data/lib/arel/nodes/unary.rb +0 -1
  236. data/lib/arel/predications.rb +17 -24
  237. data/lib/arel/select_manager.rb +1 -2
  238. data/lib/arel/table.rb +13 -5
  239. data/lib/arel/visitors.rb +0 -7
  240. data/lib/arel/visitors/dot.rb +14 -3
  241. data/lib/arel/visitors/mysql.rb +11 -1
  242. data/lib/arel/visitors/postgresql.rb +15 -5
  243. data/lib/arel/visitors/sqlite.rb +0 -1
  244. data/lib/arel/visitors/to_sql.rb +89 -79
  245. data/lib/arel/visitors/visitor.rb +0 -1
  246. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  247. data/lib/rails/generators/active_record/migration.rb +6 -2
  248. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  249. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
  250. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
  251. data/lib/rails/generators/active_record/model/model_generator.rb +38 -2
  252. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  253. metadata +27 -24
  254. data/lib/active_record/attribute_decorators.rb +0 -90
  255. data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
  256. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  257. data/lib/active_record/define_callbacks.rb +0 -22
  258. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  259. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  260. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  261. data/lib/arel/attributes.rb +0 -22
  262. data/lib/arel/visitors/depth_first.rb +0 -204
  263. data/lib/arel/visitors/ibm_db.rb +0 -34
  264. data/lib/arel/visitors/informix.rb +0 -62
  265. data/lib/arel/visitors/mssql.rb +0 -157
  266. data/lib/arel/visitors/oracle.rb +0 -159
  267. data/lib/arel/visitors/oracle12.rb +0 -66
  268. data/lib/arel/visitors/where_sql.rb +0 -23
@@ -1,157 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Arel # :nodoc: all
4
- module Visitors
5
- class MSSQL < Arel::Visitors::ToSql
6
- RowNumber = Struct.new :children
7
-
8
- def initialize(*)
9
- @primary_keys = {}
10
- super
11
- end
12
-
13
- private
14
-
15
- def visit_Arel_Nodes_IsNotDistinctFrom(o, collector)
16
- right = o.right
17
-
18
- if right.nil?
19
- collector = visit o.left, collector
20
- collector << " IS NULL"
21
- else
22
- collector << "EXISTS (VALUES ("
23
- collector = visit o.left, collector
24
- collector << ") INTERSECT VALUES ("
25
- collector = visit right, collector
26
- collector << "))"
27
- end
28
- end
29
-
30
- def visit_Arel_Nodes_IsDistinctFrom(o, collector)
31
- if o.right.nil?
32
- collector = visit o.left, collector
33
- collector << " IS NOT NULL"
34
- else
35
- collector << "NOT "
36
- visit_Arel_Nodes_IsNotDistinctFrom o, collector
37
- end
38
- end
39
-
40
- def visit_Arel_Visitors_MSSQL_RowNumber(o, collector)
41
- collector << "ROW_NUMBER() OVER (ORDER BY "
42
- inject_join(o.children, collector, ", ") << ") as _row_num"
43
- end
44
-
45
- def visit_Arel_Nodes_SelectStatement(o, collector)
46
- if !o.limit && !o.offset
47
- return super
48
- end
49
-
50
- is_select_count = false
51
- o.cores.each { |x|
52
- core_order_by = row_num_literal determine_order_by(o.orders, x)
53
- if select_count? x
54
- x.projections = [core_order_by]
55
- is_select_count = true
56
- else
57
- x.projections << core_order_by
58
- end
59
- }
60
-
61
- if is_select_count
62
- # fixme count distinct wouldn't work with limit or offset
63
- collector << "SELECT COUNT(1) as count_id FROM ("
64
- end
65
-
66
- collector << "SELECT _t.* FROM ("
67
- collector = o.cores.inject(collector) { |c, x|
68
- visit_Arel_Nodes_SelectCore x, c
69
- }
70
- collector << ") as _t WHERE #{get_offset_limit_clause(o)}"
71
-
72
- if is_select_count
73
- collector << ") AS subquery"
74
- else
75
- collector
76
- end
77
- end
78
-
79
- def visit_Arel_Nodes_SelectCore(o, collector)
80
- collector = super
81
- maybe_visit o.optimizer_hints, collector
82
- end
83
-
84
- def visit_Arel_Nodes_OptimizerHints(o, collector)
85
- hints = o.expr.map { |v| sanitize_as_sql_comment(v) }.join(", ")
86
- collector << "OPTION (#{hints})"
87
- end
88
-
89
- def get_offset_limit_clause(o)
90
- first_row = o.offset ? o.offset.expr.to_i + 1 : 1
91
- last_row = o.limit ? o.limit.expr.to_i - 1 + first_row : nil
92
- if last_row
93
- " _row_num BETWEEN #{first_row} AND #{last_row}"
94
- else
95
- " _row_num >= #{first_row}"
96
- end
97
- end
98
-
99
- def visit_Arel_Nodes_DeleteStatement(o, collector)
100
- collector << "DELETE "
101
- if o.limit
102
- collector << "TOP ("
103
- visit o.limit.expr, collector
104
- collector << ") "
105
- end
106
- collector << "FROM "
107
- collector = visit o.relation, collector
108
- if o.wheres.any?
109
- collector << " WHERE "
110
- inject_join o.wheres, collector, " AND "
111
- else
112
- collector
113
- end
114
- end
115
-
116
- def collect_optimizer_hints(o, collector)
117
- collector
118
- end
119
-
120
- def determine_order_by(orders, x)
121
- if orders.any?
122
- orders
123
- elsif x.groups.any?
124
- x.groups
125
- else
126
- pk = find_left_table_pk(x.froms)
127
- pk ? [pk] : []
128
- end
129
- end
130
-
131
- def row_num_literal(order_by)
132
- RowNumber.new order_by
133
- end
134
-
135
- def select_count?(x)
136
- x.projections.length == 1 && Arel::Nodes::Count === x.projections.first
137
- end
138
-
139
- # FIXME raise exception of there is no pk?
140
- def find_left_table_pk(o)
141
- if o.kind_of?(Arel::Nodes::Join)
142
- find_left_table_pk(o.left)
143
- elsif o.instance_of?(Arel::Table)
144
- find_primary_key(o)
145
- end
146
- end
147
-
148
- def find_primary_key(o)
149
- @primary_keys[o.name] ||= begin
150
- primary_key_name = @connection.primary_key(o.name)
151
- # some tables might be without primary key
152
- primary_key_name && o[primary_key_name]
153
- end
154
- end
155
- end
156
- end
157
- end
@@ -1,159 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Arel # :nodoc: all
4
- module Visitors
5
- class Oracle < Arel::Visitors::ToSql
6
- private
7
-
8
- def visit_Arel_Nodes_SelectStatement(o, collector)
9
- o = order_hacks(o)
10
-
11
- # if need to select first records without ORDER BY and GROUP BY and without DISTINCT
12
- # then can use simple ROWNUM in WHERE clause
13
- if o.limit && o.orders.empty? && o.cores.first.groups.empty? && !o.offset && o.cores.first.set_quantifier.class.to_s !~ /Distinct/
14
- o.cores.last.wheres.push Nodes::LessThanOrEqual.new(
15
- Nodes::SqlLiteral.new("ROWNUM"), o.limit.expr
16
- )
17
- return super
18
- end
19
-
20
- if o.limit && o.offset
21
- o = o.dup
22
- limit = o.limit.expr
23
- offset = o.offset
24
- o.offset = nil
25
- collector << "
26
- SELECT * FROM (
27
- SELECT raw_sql_.*, rownum raw_rnum_
28
- FROM ("
29
-
30
- collector = super(o, collector)
31
-
32
- if offset.expr.is_a? Nodes::BindParam
33
- collector << ") raw_sql_ WHERE rownum <= ("
34
- collector = visit offset.expr, collector
35
- collector << " + "
36
- collector = visit limit, collector
37
- collector << ") ) WHERE raw_rnum_ > "
38
- collector = visit offset.expr, collector
39
- return collector
40
- else
41
- collector << ") raw_sql_
42
- WHERE rownum <= #{offset.expr.to_i + limit}
43
- )
44
- WHERE "
45
- return visit(offset, collector)
46
- end
47
- end
48
-
49
- if o.limit
50
- o = o.dup
51
- limit = o.limit.expr
52
- collector << "SELECT * FROM ("
53
- collector = super(o, collector)
54
- collector << ") WHERE ROWNUM <= "
55
- return visit limit, collector
56
- end
57
-
58
- if o.offset
59
- o = o.dup
60
- offset = o.offset
61
- o.offset = nil
62
- collector << "SELECT * FROM (
63
- SELECT raw_sql_.*, rownum raw_rnum_
64
- FROM ("
65
- collector = super(o, collector)
66
- collector << ") raw_sql_
67
- )
68
- WHERE "
69
- return visit offset, collector
70
- end
71
-
72
- super
73
- end
74
-
75
- def visit_Arel_Nodes_Limit(o, collector)
76
- collector
77
- end
78
-
79
- def visit_Arel_Nodes_Offset(o, collector)
80
- collector << "raw_rnum_ > "
81
- visit o.expr, collector
82
- end
83
-
84
- def visit_Arel_Nodes_Except(o, collector)
85
- collector << "( "
86
- collector = infix_value o, collector, " MINUS "
87
- collector << " )"
88
- end
89
-
90
- def visit_Arel_Nodes_UpdateStatement(o, collector)
91
- # Oracle does not allow ORDER BY/LIMIT in UPDATEs.
92
- if o.orders.any? && o.limit.nil?
93
- # However, there is no harm in silently eating the ORDER BY clause if no LIMIT has been provided,
94
- # otherwise let the user deal with the error
95
- o = o.dup
96
- o.orders = []
97
- end
98
-
99
- super
100
- end
101
-
102
- ###
103
- # Hacks for the order clauses specific to Oracle
104
- def order_hacks(o)
105
- return o if o.orders.empty?
106
- return o unless o.cores.any? do |core|
107
- core.projections.any? do |projection|
108
- /FIRST_VALUE/ === projection
109
- end
110
- end
111
- # Previous version with join and split broke ORDER BY clause
112
- # if it contained functions with several arguments (separated by ',').
113
- #
114
- # orders = o.orders.map { |x| visit x }.join(', ').split(',')
115
- orders = o.orders.map do |x|
116
- string = visit(x, Arel::Collectors::SQLString.new).value
117
- if string.include?(",")
118
- split_order_string(string)
119
- else
120
- string
121
- end
122
- end.flatten
123
- o.orders = []
124
- orders.each_with_index do |order, i|
125
- o.orders <<
126
- Nodes::SqlLiteral.new("alias_#{i}__#{' DESC' if /\bdesc$/i === order}")
127
- end
128
- o
129
- end
130
-
131
- # Split string by commas but count opening and closing brackets
132
- # and ignore commas inside brackets.
133
- def split_order_string(string)
134
- array = []
135
- i = 0
136
- string.split(",").each do |part|
137
- if array[i]
138
- array[i] << "," << part
139
- else
140
- # to ensure that array[i] will be String and not Arel::Nodes::SqlLiteral
141
- array[i] = part.to_s
142
- end
143
- i += 1 if array[i].count("(") == array[i].count(")")
144
- end
145
- array
146
- end
147
-
148
- def visit_Arel_Nodes_BindParam(o, collector)
149
- collector.add_bind(o.value) { |i| ":a#{i}" }
150
- end
151
-
152
- def is_distinct_from(o, collector)
153
- collector << "DECODE("
154
- collector = visit [o.left, o.right, 0, 1], collector
155
- collector << ")"
156
- end
157
- end
158
- end
159
- end
@@ -1,66 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Arel # :nodoc: all
4
- module Visitors
5
- class Oracle12 < Arel::Visitors::ToSql
6
- private
7
-
8
- def visit_Arel_Nodes_SelectStatement(o, collector)
9
- # Oracle does not allow LIMIT clause with select for update
10
- if o.limit && o.lock
11
- raise ArgumentError, <<~MSG
12
- Combination of limit and lock is not supported. Because generated SQL statements
13
- `SELECT FOR UPDATE and FETCH FIRST n ROWS` generates ORA-02014.
14
- MSG
15
- end
16
- super
17
- end
18
-
19
- def visit_Arel_Nodes_SelectOptions(o, collector)
20
- collector = maybe_visit o.offset, collector
21
- collector = maybe_visit o.limit, collector
22
- maybe_visit o.lock, collector
23
- end
24
-
25
- def visit_Arel_Nodes_Limit(o, collector)
26
- collector << "FETCH FIRST "
27
- collector = visit o.expr, collector
28
- collector << " ROWS ONLY"
29
- end
30
-
31
- def visit_Arel_Nodes_Offset(o, collector)
32
- collector << "OFFSET "
33
- visit o.expr, collector
34
- collector << " ROWS"
35
- end
36
-
37
- def visit_Arel_Nodes_Except(o, collector)
38
- collector << "( "
39
- collector = infix_value o, collector, " MINUS "
40
- collector << " )"
41
- end
42
-
43
- def visit_Arel_Nodes_UpdateStatement(o, collector)
44
- # Oracle does not allow ORDER BY/LIMIT in UPDATEs.
45
- if o.orders.any? && o.limit.nil?
46
- # However, there is no harm in silently eating the ORDER BY clause if no LIMIT has been provided,
47
- # otherwise let the user deal with the error
48
- o = o.dup
49
- o.orders = []
50
- end
51
-
52
- super
53
- end
54
-
55
- def visit_Arel_Nodes_BindParam(o, collector)
56
- collector.add_bind(o.value) { |i| ":a#{i}" }
57
- end
58
-
59
- def is_distinct_from(o, collector)
60
- collector << "DECODE("
61
- collector = visit [o.left, o.right, 0, 1], collector
62
- collector << ")"
63
- end
64
- end
65
- end
66
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Arel # :nodoc: all
4
- module Visitors
5
- class WhereSql < Arel::Visitors::ToSql
6
- def initialize(inner_visitor, *args, &block)
7
- @inner_visitor = inner_visitor
8
- super(*args, &block)
9
- end
10
-
11
- private
12
-
13
- def visit_Arel_Nodes_SelectCore(o, collector)
14
- collector << "WHERE "
15
- wheres = o.wheres.map do |where|
16
- Nodes::SqlLiteral.new(@inner_visitor.accept(where, collector.class.new).value)
17
- end
18
-
19
- inject_join wheres, collector, " AND "
20
- end
21
- end
22
- end
23
- end