activerecord 6.0.0.beta1 → 6.0.1.rc1

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 (158) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +529 -10
  3. data/README.rdoc +3 -1
  4. data/lib/active_record.rb +7 -1
  5. data/lib/active_record/association_relation.rb +15 -6
  6. data/lib/active_record/associations.rb +4 -3
  7. data/lib/active_record/associations/association.rb +27 -2
  8. data/lib/active_record/associations/builder/association.rb +14 -18
  9. data/lib/active_record/associations/builder/belongs_to.rb +5 -2
  10. data/lib/active_record/associations/builder/collection_association.rb +5 -15
  11. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -1
  12. data/lib/active_record/associations/builder/has_many.rb +2 -0
  13. data/lib/active_record/associations/builder/has_one.rb +35 -1
  14. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  15. data/lib/active_record/associations/collection_association.rb +5 -6
  16. data/lib/active_record/associations/collection_proxy.rb +13 -42
  17. data/lib/active_record/associations/has_many_association.rb +1 -9
  18. data/lib/active_record/associations/has_many_through_association.rb +4 -11
  19. data/lib/active_record/associations/join_dependency.rb +14 -9
  20. data/lib/active_record/associations/join_dependency/join_association.rb +21 -7
  21. data/lib/active_record/associations/preloader.rb +12 -7
  22. data/lib/active_record/associations/preloader/association.rb +37 -34
  23. data/lib/active_record/associations/preloader/through_association.rb +48 -39
  24. data/lib/active_record/attribute_methods.rb +3 -53
  25. data/lib/active_record/attribute_methods/before_type_cast.rb +4 -1
  26. data/lib/active_record/attribute_methods/dirty.rb +47 -14
  27. data/lib/active_record/attribute_methods/primary_key.rb +7 -15
  28. data/lib/active_record/attribute_methods/query.rb +2 -3
  29. data/lib/active_record/attribute_methods/read.rb +3 -9
  30. data/lib/active_record/attribute_methods/write.rb +6 -12
  31. data/lib/active_record/attributes.rb +13 -0
  32. data/lib/active_record/autosave_association.rb +21 -7
  33. data/lib/active_record/base.rb +0 -1
  34. data/lib/active_record/callbacks.rb +3 -3
  35. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +134 -23
  36. data/lib/active_record/connection_adapters/abstract/database_limits.rb +8 -4
  37. data/lib/active_record/connection_adapters/abstract/database_statements.rb +105 -70
  38. data/lib/active_record/connection_adapters/abstract/query_cache.rb +12 -5
  39. data/lib/active_record/connection_adapters/abstract/quoting.rb +63 -6
  40. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +5 -2
  41. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +51 -40
  42. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -1
  43. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +95 -30
  44. data/lib/active_record/connection_adapters/abstract/transaction.rb +17 -6
  45. data/lib/active_record/connection_adapters/abstract_adapter.rb +115 -35
  46. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +106 -138
  47. data/lib/active_record/connection_adapters/column.rb +17 -13
  48. data/lib/active_record/connection_adapters/connection_specification.rb +2 -2
  49. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +3 -3
  50. data/lib/active_record/connection_adapters/mysql/database_statements.rb +48 -8
  51. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
  52. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +40 -32
  53. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +14 -6
  54. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +66 -5
  55. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +6 -10
  56. data/lib/active_record/connection_adapters/mysql2_adapter.rb +18 -5
  57. data/lib/active_record/connection_adapters/postgresql/column.rb +17 -30
  58. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +8 -2
  59. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  60. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
  61. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +6 -3
  62. data/lib/active_record/connection_adapters/postgresql/quoting.rb +40 -3
  63. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +36 -0
  64. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +98 -89
  65. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +47 -63
  66. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +23 -27
  67. data/lib/active_record/connection_adapters/postgresql_adapter.rb +95 -24
  68. data/lib/active_record/connection_adapters/schema_cache.rb +32 -14
  69. data/lib/active_record/connection_adapters/sql_type_metadata.rb +11 -8
  70. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +120 -0
  71. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +38 -2
  72. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +28 -2
  73. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +73 -118
  74. data/lib/active_record/connection_handling.rb +40 -17
  75. data/lib/active_record/core.rb +35 -24
  76. data/lib/active_record/database_configurations.rb +99 -50
  77. data/lib/active_record/database_configurations/hash_config.rb +11 -11
  78. data/lib/active_record/database_configurations/url_config.rb +21 -16
  79. data/lib/active_record/dynamic_matchers.rb +1 -1
  80. data/lib/active_record/enum.rb +15 -0
  81. data/lib/active_record/errors.rb +18 -13
  82. data/lib/active_record/fixtures.rb +11 -6
  83. data/lib/active_record/gem_version.rb +2 -2
  84. data/lib/active_record/inheritance.rb +1 -1
  85. data/lib/active_record/insert_all.rb +179 -0
  86. data/lib/active_record/integration.rb +13 -1
  87. data/lib/active_record/internal_metadata.rb +5 -1
  88. data/lib/active_record/locking/optimistic.rb +3 -4
  89. data/lib/active_record/log_subscriber.rb +1 -1
  90. data/lib/active_record/middleware/database_selector.rb +75 -0
  91. data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
  92. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  93. data/lib/active_record/migration.rb +62 -44
  94. data/lib/active_record/migration/command_recorder.rb +28 -14
  95. data/lib/active_record/migration/compatibility.rb +72 -63
  96. data/lib/active_record/model_schema.rb +3 -0
  97. data/lib/active_record/persistence.rb +212 -19
  98. data/lib/active_record/querying.rb +18 -14
  99. data/lib/active_record/railtie.rb +9 -1
  100. data/lib/active_record/railties/collection_cache_association_loading.rb +3 -3
  101. data/lib/active_record/railties/databases.rake +124 -25
  102. data/lib/active_record/reflection.rb +18 -32
  103. data/lib/active_record/relation.rb +185 -35
  104. data/lib/active_record/relation/calculations.rb +40 -44
  105. data/lib/active_record/relation/delegation.rb +23 -31
  106. data/lib/active_record/relation/finder_methods.rb +23 -14
  107. data/lib/active_record/relation/merger.rb +11 -16
  108. data/lib/active_record/relation/query_attribute.rb +5 -3
  109. data/lib/active_record/relation/query_methods.rb +230 -69
  110. data/lib/active_record/relation/spawn_methods.rb +1 -1
  111. data/lib/active_record/relation/where_clause.rb +10 -10
  112. data/lib/active_record/sanitization.rb +33 -4
  113. data/lib/active_record/schema.rb +1 -1
  114. data/lib/active_record/schema_dumper.rb +10 -1
  115. data/lib/active_record/schema_migration.rb +1 -1
  116. data/lib/active_record/scoping.rb +6 -7
  117. data/lib/active_record/scoping/default.rb +7 -15
  118. data/lib/active_record/scoping/named.rb +10 -2
  119. data/lib/active_record/statement_cache.rb +2 -2
  120. data/lib/active_record/store.rb +48 -0
  121. data/lib/active_record/table_metadata.rb +9 -13
  122. data/lib/active_record/tasks/database_tasks.rb +109 -6
  123. data/lib/active_record/tasks/mysql_database_tasks.rb +3 -1
  124. data/lib/active_record/test_databases.rb +1 -16
  125. data/lib/active_record/test_fixtures.rb +2 -2
  126. data/lib/active_record/timestamp.rb +35 -19
  127. data/lib/active_record/touch_later.rb +4 -2
  128. data/lib/active_record/transactions.rb +56 -46
  129. data/lib/active_record/type_caster/connection.rb +16 -10
  130. data/lib/active_record/validations.rb +1 -0
  131. data/lib/active_record/validations/uniqueness.rb +4 -4
  132. data/lib/arel.rb +18 -4
  133. data/lib/arel/insert_manager.rb +3 -3
  134. data/lib/arel/nodes.rb +2 -1
  135. data/lib/arel/nodes/and.rb +1 -1
  136. data/lib/arel/nodes/case.rb +1 -1
  137. data/lib/arel/nodes/comment.rb +29 -0
  138. data/lib/arel/nodes/select_core.rb +16 -12
  139. data/lib/arel/nodes/unary.rb +1 -0
  140. data/lib/arel/nodes/values_list.rb +2 -17
  141. data/lib/arel/select_manager.rb +10 -10
  142. data/lib/arel/visitors/depth_first.rb +7 -2
  143. data/lib/arel/visitors/dot.rb +7 -2
  144. data/lib/arel/visitors/ibm_db.rb +13 -0
  145. data/lib/arel/visitors/informix.rb +6 -0
  146. data/lib/arel/visitors/mssql.rb +15 -1
  147. data/lib/arel/visitors/oracle12.rb +4 -5
  148. data/lib/arel/visitors/postgresql.rb +4 -10
  149. data/lib/arel/visitors/to_sql.rb +107 -131
  150. data/lib/arel/visitors/visitor.rb +9 -5
  151. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -1
  152. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +1 -1
  153. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -2
  154. data/lib/rails/generators/active_record/model/model_generator.rb +1 -1
  155. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  156. metadata +19 -12
  157. data/lib/active_record/collection_cache_key.rb +0 -53
  158. data/lib/arel/nodes/values.rb +0 -16
@@ -9,59 +9,6 @@ module Arel # :nodoc: all
9
9
  end
10
10
 
11
11
  class ToSql < Arel::Visitors::Visitor
12
- ##
13
- # This is some roflscale crazy stuff. I'm roflscaling this because
14
- # building SQL queries is a hotspot. I will explain the roflscale so that
15
- # others will not rm this code.
16
- #
17
- # In YARV, string literals in a method body will get duped when the byte
18
- # code is executed. Let's take a look:
19
- #
20
- # > puts RubyVM::InstructionSequence.new('def foo; "bar"; end').disasm
21
- #
22
- # == disasm: <RubyVM::InstructionSequence:foo@<compiled>>=====
23
- # 0000 trace 8
24
- # 0002 trace 1
25
- # 0004 putstring "bar"
26
- # 0006 trace 16
27
- # 0008 leave
28
- #
29
- # The `putstring` bytecode will dup the string and push it on the stack.
30
- # In many cases in our SQL visitor, that string is never mutated, so there
31
- # is no need to dup the literal.
32
- #
33
- # If we change to a constant lookup, the string will not be duped, and we
34
- # can reduce the objects in our system:
35
- #
36
- # > puts RubyVM::InstructionSequence.new('BAR = "bar"; def foo; BAR; end').disasm
37
- #
38
- # == disasm: <RubyVM::InstructionSequence:foo@<compiled>>========
39
- # 0000 trace 8
40
- # 0002 trace 1
41
- # 0004 getinlinecache 11, <ic:0>
42
- # 0007 getconstant :BAR
43
- # 0009 setinlinecache <ic:0>
44
- # 0011 trace 16
45
- # 0013 leave
46
- #
47
- # `getconstant` should be a hash lookup, and no object is duped when the
48
- # value of the constant is pushed on the stack. Hence the crazy
49
- # constants below.
50
- #
51
- # `matches` and `doesNotMatch` operate case-insensitively via Visitor subclasses
52
- # specialized for specific databases when necessary.
53
- #
54
-
55
- WHERE = " WHERE " # :nodoc:
56
- SPACE = " " # :nodoc:
57
- COMMA = ", " # :nodoc:
58
- GROUP_BY = " GROUP BY " # :nodoc:
59
- ORDER_BY = " ORDER BY " # :nodoc:
60
- WINDOW = " WINDOW " # :nodoc:
61
- AND = " AND " # :nodoc:
62
-
63
- DISTINCT = "DISTINCT" # :nodoc:
64
-
65
12
  def initialize(connection)
66
13
  super()
67
14
  @connection = connection
@@ -105,10 +52,14 @@ module Arel # :nodoc: all
105
52
  def visit_Arel_Nodes_InsertStatement(o, collector)
106
53
  collector << "INSERT INTO "
107
54
  collector = visit o.relation, collector
108
- if o.columns.any?
109
- collector << " (#{o.columns.map { |x|
110
- quote_column_name x.name
111
- }.join ', '})"
55
+
56
+ unless o.columns.empty?
57
+ collector << " ("
58
+ o.columns.each_with_index do |x, i|
59
+ collector << ", " unless i == 0
60
+ collector << quote_column_name(x.name)
61
+ end
62
+ collector << ")"
112
63
  end
113
64
 
114
65
  if o.values
@@ -150,48 +101,27 @@ module Arel # :nodoc: all
150
101
  def visit_Arel_Nodes_ValuesList(o, collector)
151
102
  collector << "VALUES "
152
103
 
153
- len = o.rows.length - 1
154
- o.rows.each_with_index { |row, i|
104
+ o.rows.each_with_index do |row, i|
105
+ collector << ", " unless i == 0
155
106
  collector << "("
156
- row_len = row.length - 1
157
107
  row.each_with_index do |value, k|
108
+ collector << ", " unless k == 0
158
109
  case value
159
110
  when Nodes::SqlLiteral, Nodes::BindParam
160
111
  collector = visit(value, collector)
161
112
  else
162
- collector << quote(value)
113
+ collector << quote(value).to_s
163
114
  end
164
- collector << COMMA unless k == row_len
165
115
  end
166
116
  collector << ")"
167
- collector << COMMA unless i == len
168
- }
117
+ end
169
118
  collector
170
119
  end
171
120
 
172
- def visit_Arel_Nodes_Values(o, collector)
173
- collector << "VALUES ("
174
-
175
- len = o.expressions.length - 1
176
- o.expressions.each_with_index { |value, i|
177
- case value
178
- when Nodes::SqlLiteral, Nodes::BindParam
179
- collector = visit value, collector
180
- else
181
- collector << quote(value).to_s
182
- end
183
- unless i == len
184
- collector << COMMA
185
- end
186
- }
187
-
188
- collector << ")"
189
- end
190
-
191
121
  def visit_Arel_Nodes_SelectStatement(o, collector)
192
122
  if o.with
193
123
  collector = visit o.with, collector
194
- collector << SPACE
124
+ collector << " "
195
125
  end
196
126
 
197
127
  collector = o.cores.inject(collector) { |c, x|
@@ -199,12 +129,11 @@ module Arel # :nodoc: all
199
129
  }
200
130
 
201
131
  unless o.orders.empty?
202
- collector << ORDER_BY
203
- len = o.orders.length - 1
204
- o.orders.each_with_index { |x, i|
132
+ collector << " ORDER BY "
133
+ o.orders.each_with_index do |x, i|
134
+ collector << ", " unless i == 0
205
135
  collector = visit(x, collector)
206
- collector << COMMA unless len == i
207
- }
136
+ end
208
137
  end
209
138
 
210
139
  visit_Arel_Nodes_SelectOptions(o, collector)
@@ -219,24 +148,34 @@ module Arel # :nodoc: all
219
148
  def visit_Arel_Nodes_SelectCore(o, collector)
220
149
  collector << "SELECT"
221
150
 
151
+ collector = collect_optimizer_hints(o, collector)
222
152
  collector = maybe_visit o.set_quantifier, collector
223
153
 
224
- collect_nodes_for o.projections, collector, SPACE
154
+ collect_nodes_for o.projections, collector, " "
225
155
 
226
156
  if o.source && !o.source.empty?
227
157
  collector << " FROM "
228
158
  collector = visit o.source, collector
229
159
  end
230
160
 
231
- collect_nodes_for o.wheres, collector, WHERE, AND
232
- collect_nodes_for o.groups, collector, GROUP_BY
233
- collect_nodes_for o.havings, collector, " HAVING ", AND
234
- collect_nodes_for o.windows, collector, WINDOW
161
+ collect_nodes_for o.wheres, collector, " WHERE ", " AND "
162
+ collect_nodes_for o.groups, collector, " GROUP BY "
163
+ collect_nodes_for o.havings, collector, " HAVING ", " AND "
164
+ collect_nodes_for o.windows, collector, " WINDOW "
235
165
 
236
- collector
166
+ maybe_visit o.comment, collector
167
+ end
168
+
169
+ def visit_Arel_Nodes_OptimizerHints(o, collector)
170
+ hints = o.expr.map { |v| sanitize_as_sql_comment(v) }.join(" ")
171
+ collector << "/*+ #{hints} */"
172
+ end
173
+
174
+ def visit_Arel_Nodes_Comment(o, collector)
175
+ collector << o.values.map { |v| "/* #{sanitize_as_sql_comment(v)} */" }.join(" ")
237
176
  end
238
177
 
239
- def collect_nodes_for(nodes, collector, spacer, connector = COMMA)
178
+ def collect_nodes_for(nodes, collector, spacer, connector = ", ")
240
179
  unless nodes.empty?
241
180
  collector << spacer
242
181
  inject_join nodes, collector, connector
@@ -248,7 +187,7 @@ module Arel # :nodoc: all
248
187
  end
249
188
 
250
189
  def visit_Arel_Nodes_Distinct(o, collector)
251
- collector << DISTINCT
190
+ collector << "DISTINCT"
252
191
  end
253
192
 
254
193
  def visit_Arel_Nodes_DistinctOn(o, collector)
@@ -257,12 +196,12 @@ module Arel # :nodoc: all
257
196
 
258
197
  def visit_Arel_Nodes_With(o, collector)
259
198
  collector << "WITH "
260
- inject_join o.children, collector, COMMA
199
+ inject_join o.children, collector, ", "
261
200
  end
262
201
 
263
202
  def visit_Arel_Nodes_WithRecursive(o, collector)
264
203
  collector << "WITH RECURSIVE "
265
- inject_join o.children, collector, COMMA
204
+ inject_join o.children, collector, ", "
266
205
  end
267
206
 
268
207
  def visit_Arel_Nodes_Union(o, collector)
@@ -295,13 +234,13 @@ module Arel # :nodoc: all
295
234
  collect_nodes_for o.partitions, collector, "PARTITION BY "
296
235
 
297
236
  if o.orders.any?
298
- collector << SPACE if o.partitions.any?
237
+ collector << " " if o.partitions.any?
299
238
  collector << "ORDER BY "
300
239
  collector = inject_join o.orders, collector, ", "
301
240
  end
302
241
 
303
242
  if o.framing
304
- collector << SPACE if o.partitions.any? || o.orders.any?
243
+ collector << " " if o.partitions.any? || o.orders.any?
305
244
  collector = visit o.framing, collector
306
245
  end
307
246
 
@@ -506,8 +445,8 @@ module Arel # :nodoc: all
506
445
  collector = visit o.left, collector
507
446
  end
508
447
  if o.right.any?
509
- collector << SPACE if o.left
510
- collector = inject_join o.right, collector, SPACE
448
+ collector << " " if o.left
449
+ collector = inject_join o.right, collector, " "
511
450
  end
512
451
  collector
513
452
  end
@@ -527,7 +466,7 @@ module Arel # :nodoc: all
527
466
  def visit_Arel_Nodes_FullOuterJoin(o, collector)
528
467
  collector << "FULL OUTER JOIN "
529
468
  collector = visit o.left, collector
530
- collector << SPACE
469
+ collector << " "
531
470
  visit o.right, collector
532
471
  end
533
472
 
@@ -541,7 +480,7 @@ module Arel # :nodoc: all
541
480
  def visit_Arel_Nodes_RightOuterJoin(o, collector)
542
481
  collector << "RIGHT OUTER JOIN "
543
482
  collector = visit o.left, collector
544
- collector << SPACE
483
+ collector << " "
545
484
  visit o.right, collector
546
485
  end
547
486
 
@@ -549,7 +488,7 @@ module Arel # :nodoc: all
549
488
  collector << "INNER JOIN "
550
489
  collector = visit o.left, collector
551
490
  if o.right
552
- collector << SPACE
491
+ collector << " "
553
492
  visit(o.right, collector)
554
493
  else
555
494
  collector
@@ -568,41 +507,73 @@ module Arel # :nodoc: all
568
507
 
569
508
  def visit_Arel_Table(o, collector)
570
509
  if o.table_alias
571
- collector << "#{quote_table_name o.name} #{quote_table_name o.table_alias}"
510
+ collector << quote_table_name(o.name) << " " << quote_table_name(o.table_alias)
572
511
  else
573
512
  collector << quote_table_name(o.name)
574
513
  end
575
514
  end
576
515
 
577
516
  def visit_Arel_Nodes_In(o, collector)
578
- if Array === o.right && !o.right.empty?
517
+ unless Array === o.right
518
+ return collect_in_clause(o.left, o.right, collector)
519
+ end
520
+
521
+ unless o.right.empty?
579
522
  o.right.delete_if { |value| unboundable?(value) }
580
523
  end
581
524
 
582
- if Array === o.right && o.right.empty?
583
- collector << "1=0"
525
+ return collector << "1=0" if o.right.empty?
526
+
527
+ in_clause_length = @connection.in_clause_length
528
+
529
+ if !in_clause_length || o.right.length <= in_clause_length
530
+ collect_in_clause(o.left, o.right, collector)
584
531
  else
585
- collector = visit o.left, collector
586
- collector << " IN ("
587
- visit(o.right, collector) << ")"
532
+ collector << "("
533
+ o.right.each_slice(in_clause_length).each_with_index do |right, i|
534
+ collector << " OR " unless i == 0
535
+ collect_in_clause(o.left, right, collector)
536
+ end
537
+ collector << ")"
588
538
  end
589
539
  end
590
540
 
541
+ def collect_in_clause(left, right, collector)
542
+ collector = visit left, collector
543
+ collector << " IN ("
544
+ visit(right, collector) << ")"
545
+ end
546
+
591
547
  def visit_Arel_Nodes_NotIn(o, collector)
592
- if Array === o.right && !o.right.empty?
548
+ unless Array === o.right
549
+ return collect_not_in_clause(o.left, o.right, collector)
550
+ end
551
+
552
+ unless o.right.empty?
593
553
  o.right.delete_if { |value| unboundable?(value) }
594
554
  end
595
555
 
596
- if Array === o.right && o.right.empty?
597
- collector << "1=1"
556
+ return collector << "1=1" if o.right.empty?
557
+
558
+ in_clause_length = @connection.in_clause_length
559
+
560
+ if !in_clause_length || o.right.length <= in_clause_length
561
+ collect_not_in_clause(o.left, o.right, collector)
598
562
  else
599
- collector = visit o.left, collector
600
- collector << " NOT IN ("
601
- collector = visit o.right, collector
602
- collector << ")"
563
+ o.right.each_slice(in_clause_length).each_with_index do |right, i|
564
+ collector << " AND " unless i == 0
565
+ collect_not_in_clause(o.left, right, collector)
566
+ end
567
+ collector
603
568
  end
604
569
  end
605
570
 
571
+ def collect_not_in_clause(left, right, collector)
572
+ collector = visit left, collector
573
+ collector << " NOT IN ("
574
+ visit(right, collector) << ")"
575
+ end
576
+
606
577
  def visit_Arel_Nodes_And(o, collector)
607
578
  inject_join o.children, collector, " AND "
608
579
  end
@@ -712,13 +683,12 @@ module Arel # :nodoc: all
712
683
  end
713
684
 
714
685
  def visit_Arel_Nodes_UnqualifiedColumn(o, collector)
715
- collector << "#{quote_column_name o.name}"
716
- collector
686
+ collector << quote_column_name(o.name)
717
687
  end
718
688
 
719
689
  def visit_Arel_Attributes_Attribute(o, collector)
720
690
  join_name = o.relation.table_alias || o.relation.name
721
- collector << "#{quote_table_name join_name}.#{quote_column_name o.name}"
691
+ collector << quote_table_name(join_name) << "." << quote_column_name(o.name)
722
692
  end
723
693
  alias :visit_Arel_Attributes_Integer :visit_Arel_Attributes_Attribute
724
694
  alias :visit_Arel_Attributes_Float :visit_Arel_Attributes_Attribute
@@ -799,6 +769,15 @@ module Arel # :nodoc: all
799
769
  @connection.quote_column_name(name)
800
770
  end
801
771
 
772
+ def sanitize_as_sql_comment(value)
773
+ return value if Arel::Nodes::SqlLiteral === value
774
+ @connection.sanitize_as_sql_comment(value)
775
+ end
776
+
777
+ def collect_optimizer_hints(o, collector)
778
+ maybe_visit o.optimizer_hints, collector
779
+ end
780
+
802
781
  def maybe_visit(thing, collector)
803
782
  return collector unless thing
804
783
  collector << " "
@@ -806,14 +785,11 @@ module Arel # :nodoc: all
806
785
  end
807
786
 
808
787
  def inject_join(list, collector, join_str)
809
- len = list.length - 1
810
- list.each_with_index.inject(collector) { |c, (x, i)|
811
- if i == len
812
- visit x, c
813
- else
814
- visit(x, c) << join_str
815
- end
816
- }
788
+ list.each_with_index do |x, i|
789
+ collector << join_str unless i == 0
790
+ collector = visit(x, collector)
791
+ end
792
+ collector
817
793
  end
818
794
 
819
795
  def unboundable?(value)
@@ -7,8 +7,8 @@ module Arel # :nodoc: all
7
7
  @dispatch = get_dispatch_cache
8
8
  end
9
9
 
10
- def accept(object, *args)
11
- visit object, *args
10
+ def accept(object, collector = nil)
11
+ visit object, collector
12
12
  end
13
13
 
14
14
  private
@@ -16,7 +16,7 @@ module Arel # :nodoc: all
16
16
  attr_reader :dispatch
17
17
 
18
18
  def self.dispatch_cache
19
- Hash.new do |hash, klass|
19
+ @dispatch_cache ||= Hash.new do |hash, klass|
20
20
  hash[klass] = "visit_#{(klass.name || '').gsub('::', '_')}"
21
21
  end
22
22
  end
@@ -25,9 +25,13 @@ module Arel # :nodoc: all
25
25
  self.class.dispatch_cache
26
26
  end
27
27
 
28
- def visit(object, *args)
28
+ def visit(object, collector = nil)
29
29
  dispatch_method = dispatch[object.class]
30
- send dispatch_method, object, *args
30
+ if collector
31
+ send dispatch_method, object, collector
32
+ else
33
+ send dispatch_method, object
34
+ end
31
35
  rescue NoMethodError => e
32
36
  raise e if respond_to?(dispatch_method, true)
33
37
  superklass = object.class.ancestors.find { |klass|
@@ -8,7 +8,7 @@ module ActiveRecord
8
8
  argument :attributes, type: :array, default: [], banner: "field[:type][:index] field[:type][:index]"
9
9
 
10
10
  class_option :primary_key_type, type: :string, desc: "The type for primary key"
11
- class_option :database, type: :string, aliases: %i(db), desc: "The database for your migration. By default, the current environment's primary database is used."
11
+ class_option :database, type: :string, aliases: %i(--db), desc: "The database for your migration. By default, the current environment's primary database is used."
12
12
 
13
13
  def create_migration_file
14
14
  set_local_assigns!
@@ -6,7 +6,7 @@ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Mi
6
6
  t.string :password_digest<%= attribute.inject_options %>
7
7
  <% elsif attribute.token? -%>
8
8
  t.string :<%= attribute.name %><%= attribute.inject_options %>
9
- <% else -%>
9
+ <% elsif !attribute.virtual? -%>
10
10
  t.<%= attribute.type %> :<%= attribute.name %><%= attribute.inject_options %>
11
11
  <% end -%>
12
12
  <% end -%>