activerecord 6.0.6.1 → 6.1.7.6

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