activerecord 6.1.7 → 7.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2030 -1020
- data/MIT-LICENSE +1 -1
- data/README.rdoc +18 -18
- data/lib/active_record/aggregations.rb +17 -14
- data/lib/active_record/association_relation.rb +1 -11
- data/lib/active_record/associations/association.rb +51 -19
- data/lib/active_record/associations/association_scope.rb +17 -12
- data/lib/active_record/associations/belongs_to_association.rb +28 -9
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
- data/lib/active_record/associations/builder/association.rb +11 -5
- data/lib/active_record/associations/builder/belongs_to.rb +40 -14
- data/lib/active_record/associations/builder/collection_association.rb +10 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
- data/lib/active_record/associations/builder/has_many.rb +3 -2
- data/lib/active_record/associations/builder/has_one.rb +2 -1
- data/lib/active_record/associations/builder/singular_association.rb +6 -2
- data/lib/active_record/associations/collection_association.rb +39 -35
- data/lib/active_record/associations/collection_proxy.rb +30 -15
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +28 -18
- data/lib/active_record/associations/has_many_through_association.rb +12 -7
- data/lib/active_record/associations/has_one_association.rb +20 -10
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +3 -2
- data/lib/active_record/associations/join_dependency.rb +28 -20
- data/lib/active_record/associations/preloader/association.rb +210 -52
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +50 -14
- data/lib/active_record/associations/preloader.rb +50 -121
- data/lib/active_record/associations/singular_association.rb +9 -3
- data/lib/active_record/associations/through_association.rb +25 -14
- data/lib/active_record/associations.rb +446 -306
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +1 -3
- data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
- data/lib/active_record/attribute_methods/dirty.rb +73 -22
- data/lib/active_record/attribute_methods/primary_key.rb +78 -26
- data/lib/active_record/attribute_methods/query.rb +31 -19
- data/lib/active_record/attribute_methods/read.rb +27 -12
- data/lib/active_record/attribute_methods/serialization.rb +194 -37
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +8 -3
- data/lib/active_record/attribute_methods/write.rb +12 -15
- data/lib/active_record/attribute_methods.rb +161 -40
- data/lib/active_record/attributes.rb +27 -38
- data/lib/active_record/autosave_association.rb +65 -31
- data/lib/active_record/base.rb +25 -2
- data/lib/active_record/callbacks.rb +18 -34
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -46
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +367 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +78 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +113 -597
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +172 -50
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +87 -73
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +21 -20
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +186 -31
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +367 -141
- data/lib/active_record/connection_adapters/abstract/transaction.rb +281 -59
- data/lib/active_record/connection_adapters/abstract_adapter.rb +631 -150
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +317 -164
- data/lib/active_record/connection_adapters/column.rb +13 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +25 -134
- data/lib/active_record/connection_adapters/mysql/quoting.rb +56 -25
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +39 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +151 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +112 -55
- data/lib/active_record/connection_adapters/pool_config.rb +20 -11
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +89 -52
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +12 -3
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -56
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +92 -2
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +153 -3
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +397 -75
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +508 -246
- data/lib/active_record/connection_adapters/schema_cache.rb +319 -90
- data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +72 -53
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +37 -21
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -22
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +296 -104
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +258 -0
- data/lib/active_record/connection_adapters.rb +9 -6
- data/lib/active_record/connection_handling.rb +108 -137
- data/lib/active_record/core.rb +242 -233
- data/lib/active_record/counter_cache.rb +52 -27
- data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -2
- data/lib/active_record/database_configurations/database_config.rb +21 -12
- data/lib/active_record/database_configurations/hash_config.rb +88 -16
- data/lib/active_record/database_configurations/url_config.rb +18 -12
- data/lib/active_record/database_configurations.rb +95 -59
- data/lib/active_record/delegated_type.rb +66 -20
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +4 -2
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +1 -1
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +68 -0
- data/lib/active_record/encryption/configurable.rb +60 -0
- data/lib/active_record/encryption/context.rb +42 -0
- data/lib/active_record/encryption/contexts.rb +76 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +230 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +155 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +155 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +53 -0
- data/lib/active_record/encryption/key_provider.rb +46 -0
- data/lib/active_record/encryption/message.rb +33 -0
- data/lib/active_record/encryption/message_serializer.rb +92 -0
- data/lib/active_record/encryption/null_encryptor.rb +21 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
- data/lib/active_record/encryption/scheme.rb +100 -0
- data/lib/active_record/encryption.rb +58 -0
- data/lib/active_record/enum.rb +154 -63
- data/lib/active_record/errors.rb +172 -15
- data/lib/active_record/explain.rb +23 -3
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +15 -1
- data/lib/active_record/fixture_set/model_metadata.rb +14 -4
- data/lib/active_record/fixture_set/render_context.rb +2 -0
- data/lib/active_record/fixture_set/table_row.rb +70 -14
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +147 -86
- data/lib/active_record/future_result.rb +174 -0
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +81 -29
- data/lib/active_record/insert_all.rb +135 -22
- data/lib/active_record/integration.rb +11 -10
- data/lib/active_record/internal_metadata.rb +119 -33
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +37 -22
- data/lib/active_record/locking/pessimistic.rb +15 -6
- data/lib/active_record/log_subscriber.rb +52 -19
- data/lib/active_record/marshalling.rb +59 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +10 -10
- data/lib/active_record/middleware/database_selector.rb +23 -13
- data/lib/active_record/middleware/shard_selector.rb +62 -0
- data/lib/active_record/migration/command_recorder.rb +112 -14
- data/lib/active_record/migration/compatibility.rb +233 -46
- data/lib/active_record/migration/default_strategy.rb +23 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +361 -173
- data/lib/active_record/model_schema.rb +125 -101
- data/lib/active_record/nested_attributes.rb +50 -20
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/normalization.rb +167 -0
- data/lib/active_record/persistence.rb +409 -88
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +4 -22
- data/lib/active_record/query_logs.rb +174 -0
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +29 -6
- data/lib/active_record/railtie.rb +220 -44
- data/lib/active_record/railties/controller_runtime.rb +15 -10
- data/lib/active_record/railties/databases.rake +188 -252
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +41 -3
- data/lib/active_record/reflection.rb +248 -81
- data/lib/active_record/relation/batches/batch_enumerator.rb +23 -7
- data/lib/active_record/relation/batches.rb +192 -63
- data/lib/active_record/relation/calculations.rb +246 -90
- data/lib/active_record/relation/delegation.rb +28 -14
- data/lib/active_record/relation/finder_methods.rb +108 -51
- data/lib/active_record/relation/merger.rb +22 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +31 -3
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -7
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +27 -20
- data/lib/active_record/relation/query_attribute.rb +30 -12
- data/lib/active_record/relation/query_methods.rb +670 -129
- data/lib/active_record/relation/record_fetch_warning.rb +7 -9
- data/lib/active_record/relation/spawn_methods.rb +20 -3
- data/lib/active_record/relation/where_clause.rb +10 -19
- data/lib/active_record/relation.rb +287 -120
- data/lib/active_record/result.rb +37 -11
- data/lib/active_record/runtime_registry.rb +32 -13
- data/lib/active_record/sanitization.rb +65 -20
- data/lib/active_record/schema.rb +36 -22
- data/lib/active_record/schema_dumper.rb +73 -24
- data/lib/active_record/schema_migration.rb +68 -33
- data/lib/active_record/scoping/default.rb +72 -15
- data/lib/active_record/scoping/named.rb +5 -13
- data/lib/active_record/scoping.rb +65 -34
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/serialization.rb +6 -1
- data/lib/active_record/signed_id.rb +10 -8
- data/lib/active_record/store.rb +10 -10
- data/lib/active_record/suppressor.rb +13 -15
- data/lib/active_record/table_metadata.rb +16 -3
- data/lib/active_record/tasks/database_tasks.rb +251 -140
- data/lib/active_record/tasks/mysql_database_tasks.rb +16 -7
- data/lib/active_record/tasks/postgresql_database_tasks.rb +35 -26
- data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +117 -96
- data/lib/active_record/timestamp.rb +32 -19
- data/lib/active_record/token_for.rb +113 -0
- data/lib/active_record/touch_later.rb +11 -6
- data/lib/active_record/transactions.rb +48 -27
- data/lib/active_record/translation.rb +3 -3
- data/lib/active_record/type/adapter_specific_registry.rb +32 -14
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +9 -5
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/type/type_map.rb +17 -20
- data/lib/active_record/type.rb +1 -2
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +4 -4
- data/lib/active_record/validations/numericality.rb +5 -4
- data/lib/active_record/validations/presence.rb +5 -28
- data/lib/active_record/validations/uniqueness.rb +51 -6
- data/lib/active_record/validations.rb +8 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +335 -32
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/crud.rb +28 -22
- data/lib/arel/delete_manager.rb +18 -4
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/and.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -1
- data/lib/arel/nodes/bound_sql_literal.rb +61 -0
- data/lib/arel/nodes/casted.rb +1 -1
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/delete_statement.rb +12 -13
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/homogeneous_in.rb +1 -9
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/node.rb +111 -2
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +6 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes/update_statement.rb +8 -3
- data/lib/arel/nodes.rb +5 -0
- data/lib/arel/predications.rb +13 -3
- data/lib/arel/select_manager.rb +10 -4
- data/lib/arel/table.rb +9 -6
- data/lib/arel/tree_manager.rb +5 -13
- data/lib/arel/update_manager.rb +18 -4
- data/lib/arel/visitors/dot.rb +80 -90
- data/lib/arel/visitors/mysql.rb +16 -3
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +141 -20
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +18 -3
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration.rb +3 -1
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
- data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
- data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
- metadata +96 -16
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -67
data/lib/arel/visitors/dot.rb
CHANGED
@@ -31,6 +31,40 @@ module Arel # :nodoc: all
|
|
31
31
|
end
|
32
32
|
|
33
33
|
private
|
34
|
+
def visit_Arel_Nodes_Function(o)
|
35
|
+
visit_edge o, "expressions"
|
36
|
+
visit_edge o, "distinct"
|
37
|
+
visit_edge o, "alias"
|
38
|
+
end
|
39
|
+
|
40
|
+
def visit_Arel_Nodes_Unary(o)
|
41
|
+
visit_edge o, "expr"
|
42
|
+
end
|
43
|
+
|
44
|
+
def visit_Arel_Nodes_Binary(o)
|
45
|
+
visit_edge o, "left"
|
46
|
+
visit_edge o, "right"
|
47
|
+
end
|
48
|
+
|
49
|
+
def visit_Arel_Nodes_UnaryOperation(o)
|
50
|
+
visit_edge o, "operator"
|
51
|
+
visit_edge o, "expr"
|
52
|
+
end
|
53
|
+
|
54
|
+
def visit_Arel_Nodes_InfixOperation(o)
|
55
|
+
visit_edge o, "operator"
|
56
|
+
visit_edge o, "left"
|
57
|
+
visit_edge o, "right"
|
58
|
+
end
|
59
|
+
|
60
|
+
def visit__regexp(o)
|
61
|
+
visit_edge o, "left"
|
62
|
+
visit_edge o, "right"
|
63
|
+
visit_edge o, "case_sensitive"
|
64
|
+
end
|
65
|
+
alias :visit_Arel_Nodes_Regexp :visit__regexp
|
66
|
+
alias :visit_Arel_Nodes_NotRegexp :visit__regexp
|
67
|
+
|
34
68
|
def visit_Arel_Nodes_Ordering(o)
|
35
69
|
visit_edge o, "expr"
|
36
70
|
end
|
@@ -53,71 +87,29 @@ module Arel # :nodoc: all
|
|
53
87
|
visit_edge o, "left"
|
54
88
|
end
|
55
89
|
|
56
|
-
def
|
57
|
-
visit_edge o, "left"
|
58
|
-
visit_edge o, "right"
|
59
|
-
end
|
60
|
-
alias :visit_Arel_Nodes_FullOuterJoin :visit_Arel_Nodes_InnerJoin
|
61
|
-
alias :visit_Arel_Nodes_OuterJoin :visit_Arel_Nodes_InnerJoin
|
62
|
-
alias :visit_Arel_Nodes_RightOuterJoin :visit_Arel_Nodes_InnerJoin
|
63
|
-
|
64
|
-
def visit_Arel_Nodes_DeleteStatement(o)
|
65
|
-
visit_edge o, "relation"
|
66
|
-
visit_edge o, "wheres"
|
67
|
-
end
|
68
|
-
|
69
|
-
def unary(o)
|
70
|
-
visit_edge o, "expr"
|
71
|
-
end
|
72
|
-
alias :visit_Arel_Nodes_Group :unary
|
73
|
-
alias :visit_Arel_Nodes_Cube :unary
|
74
|
-
alias :visit_Arel_Nodes_RollUp :unary
|
75
|
-
alias :visit_Arel_Nodes_GroupingSet :unary
|
76
|
-
alias :visit_Arel_Nodes_GroupingElement :unary
|
77
|
-
alias :visit_Arel_Nodes_Grouping :unary
|
78
|
-
alias :visit_Arel_Nodes_Having :unary
|
79
|
-
alias :visit_Arel_Nodes_Limit :unary
|
80
|
-
alias :visit_Arel_Nodes_Not :unary
|
81
|
-
alias :visit_Arel_Nodes_Offset :unary
|
82
|
-
alias :visit_Arel_Nodes_On :unary
|
83
|
-
alias :visit_Arel_Nodes_UnqualifiedColumn :unary
|
84
|
-
alias :visit_Arel_Nodes_OptimizerHints :unary
|
85
|
-
alias :visit_Arel_Nodes_Preceding :unary
|
86
|
-
alias :visit_Arel_Nodes_Following :unary
|
87
|
-
alias :visit_Arel_Nodes_Rows :unary
|
88
|
-
alias :visit_Arel_Nodes_Range :unary
|
89
|
-
|
90
|
-
def window(o)
|
90
|
+
def visit_Arel_Nodes_Window(o)
|
91
91
|
visit_edge o, "partitions"
|
92
92
|
visit_edge o, "orders"
|
93
93
|
visit_edge o, "framing"
|
94
94
|
end
|
95
|
-
alias :visit_Arel_Nodes_Window :window
|
96
95
|
|
97
|
-
def
|
96
|
+
def visit_Arel_Nodes_NamedWindow(o)
|
98
97
|
visit_edge o, "partitions"
|
99
98
|
visit_edge o, "orders"
|
100
99
|
visit_edge o, "framing"
|
101
100
|
visit_edge o, "name"
|
102
101
|
end
|
103
|
-
alias :visit_Arel_Nodes_NamedWindow :named_window
|
104
102
|
|
105
|
-
def
|
106
|
-
|
107
|
-
visit_edge o, "distinct"
|
108
|
-
visit_edge o, "alias"
|
103
|
+
def visit__no_edges(o)
|
104
|
+
# intentionally left blank
|
109
105
|
end
|
110
|
-
alias :
|
111
|
-
alias :
|
112
|
-
alias :visit_Arel_Nodes_Max :function
|
113
|
-
alias :visit_Arel_Nodes_Avg :function
|
114
|
-
alias :visit_Arel_Nodes_Sum :function
|
106
|
+
alias :visit_Arel_Nodes_CurrentRow :visit__no_edges
|
107
|
+
alias :visit_Arel_Nodes_Distinct :visit__no_edges
|
115
108
|
|
116
|
-
def
|
109
|
+
def visit_Arel_Nodes_Extract(o)
|
117
110
|
visit_edge o, "expressions"
|
118
111
|
visit_edge o, "alias"
|
119
112
|
end
|
120
|
-
alias :visit_Arel_Nodes_Extract :extract
|
121
113
|
|
122
114
|
def visit_Arel_Nodes_NamedFunction(o)
|
123
115
|
visit_edge o, "name"
|
@@ -130,13 +122,19 @@ module Arel # :nodoc: all
|
|
130
122
|
visit_edge o, "relation"
|
131
123
|
visit_edge o, "columns"
|
132
124
|
visit_edge o, "values"
|
125
|
+
visit_edge o, "select"
|
133
126
|
end
|
134
127
|
|
135
128
|
def visit_Arel_Nodes_SelectCore(o)
|
136
129
|
visit_edge o, "source"
|
137
130
|
visit_edge o, "projections"
|
138
131
|
visit_edge o, "wheres"
|
139
|
-
visit_edge o,
|
132
|
+
visit_edge o, "windows"
|
133
|
+
visit_edge o, "groups"
|
134
|
+
visit_edge o, "comment"
|
135
|
+
visit_edge o, "havings"
|
136
|
+
visit_edge o, "set_quantifier"
|
137
|
+
visit_edge o, "optimizer_hints"
|
140
138
|
end
|
141
139
|
|
142
140
|
def visit_Arel_Nodes_SelectStatement(o)
|
@@ -144,12 +142,27 @@ module Arel # :nodoc: all
|
|
144
142
|
visit_edge o, "limit"
|
145
143
|
visit_edge o, "orders"
|
146
144
|
visit_edge o, "offset"
|
145
|
+
visit_edge o, "lock"
|
146
|
+
visit_edge o, "with"
|
147
147
|
end
|
148
148
|
|
149
149
|
def visit_Arel_Nodes_UpdateStatement(o)
|
150
150
|
visit_edge o, "relation"
|
151
151
|
visit_edge o, "wheres"
|
152
152
|
visit_edge o, "values"
|
153
|
+
visit_edge o, "orders"
|
154
|
+
visit_edge o, "limit"
|
155
|
+
visit_edge o, "offset"
|
156
|
+
visit_edge o, "key"
|
157
|
+
end
|
158
|
+
|
159
|
+
def visit_Arel_Nodes_DeleteStatement(o)
|
160
|
+
visit_edge o, "relation"
|
161
|
+
visit_edge o, "wheres"
|
162
|
+
visit_edge o, "orders"
|
163
|
+
visit_edge o, "limit"
|
164
|
+
visit_edge o, "offset"
|
165
|
+
visit_edge o, "key"
|
153
166
|
end
|
154
167
|
|
155
168
|
def visit_Arel_Table(o)
|
@@ -167,47 +180,18 @@ module Arel # :nodoc: all
|
|
167
180
|
visit_edge o, "attribute"
|
168
181
|
end
|
169
182
|
|
170
|
-
def
|
183
|
+
def visit_Arel_Attributes_Attribute(o)
|
171
184
|
visit_edge o, "relation"
|
172
185
|
visit_edge o, "name"
|
173
186
|
end
|
174
|
-
alias :visit_Arel_Attributes_Integer :visit_Arel_Attribute
|
175
|
-
alias :visit_Arel_Attributes_Float :visit_Arel_Attribute
|
176
|
-
alias :visit_Arel_Attributes_String :visit_Arel_Attribute
|
177
|
-
alias :visit_Arel_Attributes_Time :visit_Arel_Attribute
|
178
|
-
alias :visit_Arel_Attributes_Boolean :visit_Arel_Attribute
|
179
|
-
alias :visit_Arel_Attributes_Attribute :visit_Arel_Attribute
|
180
187
|
|
181
|
-
def
|
182
|
-
o.children.each_with_index do |
|
183
|
-
edge(i) { visit
|
188
|
+
def visit__children(o)
|
189
|
+
o.children.each_with_index do |child, i|
|
190
|
+
edge(i) { visit child }
|
184
191
|
end
|
185
192
|
end
|
186
|
-
alias :visit_Arel_Nodes_And :
|
187
|
-
|
188
|
-
def binary(o)
|
189
|
-
visit_edge o, "left"
|
190
|
-
visit_edge o, "right"
|
191
|
-
end
|
192
|
-
alias :visit_Arel_Nodes_As :binary
|
193
|
-
alias :visit_Arel_Nodes_Assignment :binary
|
194
|
-
alias :visit_Arel_Nodes_Between :binary
|
195
|
-
alias :visit_Arel_Nodes_Concat :binary
|
196
|
-
alias :visit_Arel_Nodes_DoesNotMatch :binary
|
197
|
-
alias :visit_Arel_Nodes_Equality :binary
|
198
|
-
alias :visit_Arel_Nodes_GreaterThan :binary
|
199
|
-
alias :visit_Arel_Nodes_GreaterThanOrEqual :binary
|
200
|
-
alias :visit_Arel_Nodes_In :binary
|
201
|
-
alias :visit_Arel_Nodes_JoinSource :binary
|
202
|
-
alias :visit_Arel_Nodes_LessThan :binary
|
203
|
-
alias :visit_Arel_Nodes_LessThanOrEqual :binary
|
204
|
-
alias :visit_Arel_Nodes_IsNotDistinctFrom :binary
|
205
|
-
alias :visit_Arel_Nodes_IsDistinctFrom :binary
|
206
|
-
alias :visit_Arel_Nodes_Matches :binary
|
207
|
-
alias :visit_Arel_Nodes_NotEqual :binary
|
208
|
-
alias :visit_Arel_Nodes_NotIn :binary
|
209
|
-
alias :visit_Arel_Nodes_Or :binary
|
210
|
-
alias :visit_Arel_Nodes_Over :binary
|
193
|
+
alias :visit_Arel_Nodes_And :visit__children
|
194
|
+
alias :visit_Arel_Nodes_With :visit__children
|
211
195
|
|
212
196
|
def visit_String(o)
|
213
197
|
@node_stack.last.fields << o
|
@@ -225,22 +209,22 @@ module Arel # :nodoc: all
|
|
225
209
|
alias :visit_Arel_Nodes_SqlLiteral :visit_String
|
226
210
|
|
227
211
|
def visit_Arel_Nodes_BindParam(o)
|
228
|
-
|
212
|
+
visit_edge(o, "value")
|
229
213
|
end
|
230
214
|
|
231
215
|
def visit_ActiveModel_Attribute(o)
|
232
|
-
|
216
|
+
visit_edge(o, "value_before_type_cast")
|
233
217
|
end
|
234
218
|
|
235
219
|
def visit_Hash(o)
|
236
220
|
o.each_with_index do |pair, i|
|
237
|
-
edge("pair_#{i}")
|
221
|
+
edge("pair_#{i}") { visit pair }
|
238
222
|
end
|
239
223
|
end
|
240
224
|
|
241
225
|
def visit_Array(o)
|
242
|
-
o.each_with_index do |
|
243
|
-
edge(i) { visit
|
226
|
+
o.each_with_index do |member, i|
|
227
|
+
edge(i) { visit member }
|
244
228
|
end
|
245
229
|
end
|
246
230
|
alias :visit_Set :visit_Array
|
@@ -249,6 +233,12 @@ module Arel # :nodoc: all
|
|
249
233
|
visit_edge(o, "values")
|
250
234
|
end
|
251
235
|
|
236
|
+
def visit_Arel_Nodes_Case(o)
|
237
|
+
visit_edge(o, "case")
|
238
|
+
visit_edge(o, "conditions")
|
239
|
+
visit_edge(o, "default")
|
240
|
+
end
|
241
|
+
|
252
242
|
def visit_edge(o, method)
|
253
243
|
edge(method) { visit o.send(method) }
|
254
244
|
end
|
data/lib/arel/visitors/mysql.rb
CHANGED
@@ -5,8 +5,9 @@ module Arel # :nodoc: all
|
|
5
5
|
class MySQL < Arel::Visitors::ToSql
|
6
6
|
private
|
7
7
|
def visit_Arel_Nodes_Bin(o, collector)
|
8
|
-
collector << "
|
8
|
+
collector << "CAST("
|
9
9
|
visit o.expr, collector
|
10
|
+
collector << " AS BINARY)"
|
10
11
|
end
|
11
12
|
|
12
13
|
def visit_Arel_Nodes_UnqualifiedColumn(o, collector)
|
@@ -58,11 +59,23 @@ module Arel # :nodoc: all
|
|
58
59
|
infix_value o, collector, " NOT REGEXP "
|
59
60
|
end
|
60
61
|
|
62
|
+
# no-op
|
63
|
+
def visit_Arel_Nodes_NullsFirst(o, collector)
|
64
|
+
visit o.expr, collector
|
65
|
+
end
|
66
|
+
|
67
|
+
def visit_Arel_Nodes_Cte(o, collector)
|
68
|
+
collector << quote_table_name(o.name)
|
69
|
+
collector << " AS "
|
70
|
+
visit o.relation, collector
|
71
|
+
end
|
72
|
+
|
61
73
|
# In the simple case, MySQL allows us to place JOINs directly into the UPDATE
|
62
74
|
# query. However, this does not allow for LIMIT, OFFSET and ORDER. To support
|
63
75
|
# these, we must use a subquery.
|
64
76
|
def prepare_update_statement(o)
|
65
|
-
if o.offset ||
|
77
|
+
if o.offset || has_group_by_and_having?(o) ||
|
78
|
+
has_join_sources?(o) && has_limit_or_offset_or_orders?(o)
|
66
79
|
super
|
67
80
|
else
|
68
81
|
o
|
@@ -70,7 +83,7 @@ module Arel # :nodoc: all
|
|
70
83
|
end
|
71
84
|
alias :prepare_delete_statement :prepare_update_statement
|
72
85
|
|
73
|
-
# MySQL
|
86
|
+
# MySQL doesn't automatically create a temporary table for use subquery, so we have
|
74
87
|
# to give it some prompting in the form of a subsubquery.
|
75
88
|
def build_subselect(key, o)
|
76
89
|
subselect = super
|
@@ -78,16 +78,6 @@ module Arel # :nodoc: all
|
|
78
78
|
visit o.right, collector
|
79
79
|
end
|
80
80
|
|
81
|
-
def visit_Arel_Nodes_NullsFirst(o, collector)
|
82
|
-
visit o.expr, collector
|
83
|
-
collector << " NULLS FIRST"
|
84
|
-
end
|
85
|
-
|
86
|
-
def visit_Arel_Nodes_NullsLast(o, collector)
|
87
|
-
visit o.expr, collector
|
88
|
-
collector << " NULLS LAST"
|
89
|
-
end
|
90
|
-
|
91
81
|
BIND_BLOCK = proc { |i| "$#{i}" }
|
92
82
|
private_constant :BIND_BLOCK
|
93
83
|
|
data/lib/arel/visitors/to_sql.rb
CHANGED
@@ -103,7 +103,7 @@ module Arel # :nodoc: all
|
|
103
103
|
row.each_with_index do |value, k|
|
104
104
|
collector << ", " unless k == 0
|
105
105
|
case value
|
106
|
-
when Nodes::SqlLiteral, Nodes::BindParam
|
106
|
+
when Nodes::SqlLiteral, Nodes::BindParam, ActiveModel::Attribute
|
107
107
|
collector = visit(value, collector)
|
108
108
|
else
|
109
109
|
collector << quote(value).to_s
|
@@ -135,6 +135,8 @@ module Arel # :nodoc: all
|
|
135
135
|
visit_Arel_Nodes_SelectOptions(o, collector)
|
136
136
|
end
|
137
137
|
|
138
|
+
# The Oracle enhanced adapter uses this private method,
|
139
|
+
# see https://github.com/rsim/oracle-enhanced/issues/2186
|
138
140
|
def visit_Arel_Nodes_SelectOptions(o, collector)
|
139
141
|
collector = maybe_visit o.limit, collector
|
140
142
|
collector = maybe_visit o.offset, collector
|
@@ -243,6 +245,13 @@ module Arel # :nodoc: all
|
|
243
245
|
collector << ")"
|
244
246
|
end
|
245
247
|
|
248
|
+
def visit_Arel_Nodes_Filter(o, collector)
|
249
|
+
visit o.left, collector
|
250
|
+
collector << " FILTER (WHERE "
|
251
|
+
visit o.right, collector
|
252
|
+
collector << ")"
|
253
|
+
end
|
254
|
+
|
246
255
|
def visit_Arel_Nodes_Rows(o, collector)
|
247
256
|
if o.expr
|
248
257
|
collector << "ROWS "
|
@@ -324,7 +333,7 @@ module Arel # :nodoc: all
|
|
324
333
|
def visit_Arel_Nodes_HomogeneousIn(o, collector)
|
325
334
|
collector.preparable = false
|
326
335
|
|
327
|
-
|
336
|
+
visit o.left, collector
|
328
337
|
|
329
338
|
if o.type == :in
|
330
339
|
collector << " IN ("
|
@@ -341,7 +350,6 @@ module Arel # :nodoc: all
|
|
341
350
|
end
|
342
351
|
|
343
352
|
collector << ")"
|
344
|
-
collector
|
345
353
|
end
|
346
354
|
|
347
355
|
def visit_Arel_SelectManager(o, collector)
|
@@ -357,6 +365,17 @@ module Arel # :nodoc: all
|
|
357
365
|
visit(o.expr, collector) << " DESC"
|
358
366
|
end
|
359
367
|
|
368
|
+
# NullsFirst is available on all but MySQL, where it is redefined.
|
369
|
+
def visit_Arel_Nodes_NullsFirst(o, collector)
|
370
|
+
visit o.expr, collector
|
371
|
+
collector << " NULLS FIRST"
|
372
|
+
end
|
373
|
+
|
374
|
+
def visit_Arel_Nodes_NullsLast(o, collector)
|
375
|
+
visit o.expr, collector
|
376
|
+
collector << " NULLS LAST"
|
377
|
+
end
|
378
|
+
|
360
379
|
def visit_Arel_Nodes_Group(o, collector)
|
361
380
|
visit o.expr, collector
|
362
381
|
end
|
@@ -412,24 +431,48 @@ module Arel # :nodoc: all
|
|
412
431
|
end
|
413
432
|
|
414
433
|
def visit_Arel_Nodes_GreaterThanOrEqual(o, collector)
|
434
|
+
case unboundable?(o.right)
|
435
|
+
when 1
|
436
|
+
return collector << "1=0"
|
437
|
+
when -1
|
438
|
+
return collector << "1=1"
|
439
|
+
end
|
415
440
|
collector = visit o.left, collector
|
416
441
|
collector << " >= "
|
417
442
|
visit o.right, collector
|
418
443
|
end
|
419
444
|
|
420
445
|
def visit_Arel_Nodes_GreaterThan(o, collector)
|
446
|
+
case unboundable?(o.right)
|
447
|
+
when 1
|
448
|
+
return collector << "1=0"
|
449
|
+
when -1
|
450
|
+
return collector << "1=1"
|
451
|
+
end
|
421
452
|
collector = visit o.left, collector
|
422
453
|
collector << " > "
|
423
454
|
visit o.right, collector
|
424
455
|
end
|
425
456
|
|
426
457
|
def visit_Arel_Nodes_LessThanOrEqual(o, collector)
|
458
|
+
case unboundable?(o.right)
|
459
|
+
when 1
|
460
|
+
return collector << "1=1"
|
461
|
+
when -1
|
462
|
+
return collector << "1=0"
|
463
|
+
end
|
427
464
|
collector = visit o.left, collector
|
428
465
|
collector << " <= "
|
429
466
|
visit o.right, collector
|
430
467
|
end
|
431
468
|
|
432
469
|
def visit_Arel_Nodes_LessThan(o, collector)
|
470
|
+
case unboundable?(o.right)
|
471
|
+
when 1
|
472
|
+
return collector << "1=1"
|
473
|
+
when -1
|
474
|
+
return collector << "1=0"
|
475
|
+
end
|
433
476
|
collector = visit o.left, collector
|
434
477
|
collector << " < "
|
435
478
|
visit o.right, collector
|
@@ -525,11 +568,17 @@ module Arel # :nodoc: all
|
|
525
568
|
end
|
526
569
|
|
527
570
|
def visit_Arel_Table(o, collector)
|
528
|
-
if o.
|
529
|
-
|
571
|
+
if Arel::Nodes::Node === o.name
|
572
|
+
visit o.name, collector
|
530
573
|
else
|
531
574
|
collector << quote_table_name(o.name)
|
532
575
|
end
|
576
|
+
|
577
|
+
if o.table_alias
|
578
|
+
collector << " " << quote_table_name(o.table_alias)
|
579
|
+
end
|
580
|
+
|
581
|
+
collector
|
533
582
|
end
|
534
583
|
|
535
584
|
def visit_Arel_Nodes_In(o, collector)
|
@@ -585,7 +634,7 @@ module Arel # :nodoc: all
|
|
585
634
|
|
586
635
|
def visit_Arel_Nodes_Assignment(o, collector)
|
587
636
|
case o.right
|
588
|
-
when Arel::Nodes::Node, Arel::Attributes::Attribute
|
637
|
+
when Arel::Nodes::Node, Arel::Attributes::Attribute, ActiveModel::Attribute
|
589
638
|
collector = visit o.left, collector
|
590
639
|
collector << " = "
|
591
640
|
visit o.right, collector
|
@@ -685,6 +734,20 @@ module Arel # :nodoc: all
|
|
685
734
|
collector << quote_column_name(o.name)
|
686
735
|
end
|
687
736
|
|
737
|
+
def visit_Arel_Nodes_Cte(o, collector)
|
738
|
+
collector << quote_table_name(o.name)
|
739
|
+
collector << " AS "
|
740
|
+
|
741
|
+
case o.materialized
|
742
|
+
when true
|
743
|
+
collector << "MATERIALIZED "
|
744
|
+
when false
|
745
|
+
collector << "NOT MATERIALIZED "
|
746
|
+
end
|
747
|
+
|
748
|
+
visit o.relation, collector
|
749
|
+
end
|
750
|
+
|
688
751
|
def visit_Arel_Attributes_Attribute(o, collector)
|
689
752
|
join_name = o.relation.table_alias || o.relation.name
|
690
753
|
collector << quote_table_name(join_name) << "." << quote_column_name(o.name)
|
@@ -695,6 +758,10 @@ module Arel # :nodoc: all
|
|
695
758
|
|
696
759
|
def bind_block; BIND_BLOCK; end
|
697
760
|
|
761
|
+
def visit_ActiveModel_Attribute(o, collector)
|
762
|
+
collector.add_bind(o, &bind_block)
|
763
|
+
end
|
764
|
+
|
698
765
|
def visit_Arel_Nodes_BindParam(o, collector)
|
699
766
|
collector.add_bind(o.value, &bind_block)
|
700
767
|
end
|
@@ -704,6 +771,59 @@ module Arel # :nodoc: all
|
|
704
771
|
collector << o.to_s
|
705
772
|
end
|
706
773
|
|
774
|
+
def visit_Arel_Nodes_BoundSqlLiteral(o, collector)
|
775
|
+
bind_index = 0
|
776
|
+
|
777
|
+
new_bind = lambda do |value|
|
778
|
+
if Arel.arel_node?(value)
|
779
|
+
visit value, collector
|
780
|
+
elsif value.is_a?(Array)
|
781
|
+
if value.empty?
|
782
|
+
collector << @connection.quote(nil)
|
783
|
+
else
|
784
|
+
if value.none? { |v| Arel.arel_node?(v) }
|
785
|
+
collector.add_binds(value.map { |v| @connection.cast_bound_value(v) }, &bind_block)
|
786
|
+
else
|
787
|
+
value.each_with_index do |v, i|
|
788
|
+
collector << ", " unless i == 0
|
789
|
+
if Arel.arel_node?(v)
|
790
|
+
visit v, collector
|
791
|
+
else
|
792
|
+
collector.add_bind(@connection.cast_bound_value(v), &bind_block)
|
793
|
+
end
|
794
|
+
end
|
795
|
+
end
|
796
|
+
end
|
797
|
+
else
|
798
|
+
collector.add_bind(@connection.cast_bound_value(value), &bind_block)
|
799
|
+
end
|
800
|
+
end
|
801
|
+
|
802
|
+
if o.positional_binds
|
803
|
+
o.sql_with_placeholders.scan(/\?|([^?]+)/) do
|
804
|
+
if $1
|
805
|
+
collector << $1
|
806
|
+
else
|
807
|
+
value = o.positional_binds[bind_index]
|
808
|
+
bind_index += 1
|
809
|
+
|
810
|
+
new_bind.call(value)
|
811
|
+
end
|
812
|
+
end
|
813
|
+
else
|
814
|
+
o.sql_with_placeholders.scan(/:(?<!::)([a-zA-Z]\w*)|([^:]+|.)/) do
|
815
|
+
if $2
|
816
|
+
collector << $2
|
817
|
+
else
|
818
|
+
value = o.named_binds[$1.to_sym]
|
819
|
+
new_bind.call(value)
|
820
|
+
end
|
821
|
+
end
|
822
|
+
end
|
823
|
+
|
824
|
+
collector
|
825
|
+
end
|
826
|
+
|
707
827
|
def visit_Integer(o, collector)
|
708
828
|
collector << o.to_s
|
709
829
|
end
|
@@ -743,6 +863,10 @@ module Arel # :nodoc: all
|
|
743
863
|
end
|
744
864
|
alias :visit_Set :visit_Array
|
745
865
|
|
866
|
+
def visit_Arel_Nodes_Fragments(o, collector)
|
867
|
+
inject_join o.values, collector, " "
|
868
|
+
end
|
869
|
+
|
746
870
|
def quote(value)
|
747
871
|
return value if Arel::Nodes::SqlLiteral === value
|
748
872
|
@connection.quote value
|
@@ -793,6 +917,10 @@ module Arel # :nodoc: all
|
|
793
917
|
o.limit || o.offset || !o.orders.empty?
|
794
918
|
end
|
795
919
|
|
920
|
+
def has_group_by_and_having?(o)
|
921
|
+
!o.groups.empty? && !o.havings.empty?
|
922
|
+
end
|
923
|
+
|
796
924
|
# The default strategy for an UPDATE with joins is to use a subquery. This doesn't work
|
797
925
|
# on MySQL (even when aliasing the tables), but MySQL allows using JOIN directly in
|
798
926
|
# an UPDATE statement, so in the MySQL visitor we redefine this to do that.
|
@@ -802,8 +930,11 @@ module Arel # :nodoc: all
|
|
802
930
|
stmt.limit = nil
|
803
931
|
stmt.offset = nil
|
804
932
|
stmt.orders = []
|
805
|
-
|
933
|
+
columns = Arel::Nodes::Grouping.new(o.key)
|
934
|
+
stmt.wheres = [Nodes::In.new(columns, [build_subselect(o.key, o)])]
|
806
935
|
stmt.relation = o.relation.left if has_join_sources?(o)
|
936
|
+
stmt.groups = o.groups unless o.groups.empty?
|
937
|
+
stmt.havings = o.havings unless o.havings.empty?
|
807
938
|
stmt
|
808
939
|
else
|
809
940
|
o
|
@@ -818,6 +949,8 @@ module Arel # :nodoc: all
|
|
818
949
|
core.froms = o.relation
|
819
950
|
core.wheres = o.wheres
|
820
951
|
core.projections = [key]
|
952
|
+
core.groups = o.groups unless o.groups.empty?
|
953
|
+
core.havings = o.havings unless o.havings.empty?
|
821
954
|
stmt.limit = o.limit
|
822
955
|
stmt.offset = o.offset
|
823
956
|
stmt.orders = o.orders
|
@@ -877,19 +1010,7 @@ module Arel # :nodoc: all
|
|
877
1010
|
def collect_ctes(children, collector)
|
878
1011
|
children.each_with_index do |child, i|
|
879
1012
|
collector << ", " unless i == 0
|
880
|
-
|
881
|
-
case child
|
882
|
-
when Arel::Nodes::As
|
883
|
-
name = child.left.name
|
884
|
-
relation = child.right
|
885
|
-
when Arel::Nodes::TableAlias
|
886
|
-
name = child.name
|
887
|
-
relation = child.relation
|
888
|
-
end
|
889
|
-
|
890
|
-
collector << quote_table_name(name)
|
891
|
-
collector << " AS "
|
892
|
-
visit relation, collector
|
1013
|
+
visit child.to_cte, collector
|
893
1014
|
end
|
894
1015
|
|
895
1016
|
collector
|
@@ -16,8 +16,8 @@ module Arel # :nodoc: all
|
|
16
16
|
|
17
17
|
def self.dispatch_cache
|
18
18
|
@dispatch_cache ||= Hash.new do |hash, klass|
|
19
|
-
hash[klass] = "visit_#{(klass.name ||
|
20
|
-
end
|
19
|
+
hash[klass] = :"visit_#{(klass.name || "").gsub("::", "_")}"
|
20
|
+
end.compare_by_identity
|
21
21
|
end
|
22
22
|
|
23
23
|
def get_dispatch_cache
|
data/lib/arel.rb
CHANGED
@@ -7,6 +7,7 @@ require "arel/factory_methods"
|
|
7
7
|
|
8
8
|
require "arel/expressions"
|
9
9
|
require "arel/predications"
|
10
|
+
require "arel/filter_predications"
|
10
11
|
require "arel/window_predications"
|
11
12
|
require "arel/math"
|
12
13
|
require "arel/alias_predication"
|
@@ -29,13 +30,27 @@ module Arel
|
|
29
30
|
|
30
31
|
# Wrap a known-safe SQL string for passing to query methods, e.g.
|
31
32
|
#
|
32
|
-
# Post.order(Arel.sql("
|
33
|
+
# Post.order(Arel.sql("REPLACE(title, 'misc', 'zzzz') asc")).pluck(:id)
|
33
34
|
#
|
34
35
|
# Great caution should be taken to avoid SQL injection vulnerabilities.
|
35
36
|
# This method should not be used with unsafe values such as request
|
36
37
|
# parameters or model attributes.
|
37
|
-
|
38
|
-
|
38
|
+
#
|
39
|
+
# Take a look at the {security guide}[https://guides.rubyonrails.org/security.html#sql-injection]
|
40
|
+
# for more information.
|
41
|
+
#
|
42
|
+
# To construct a more complex query fragment, including the possible
|
43
|
+
# use of user-provided values, the +sql_string+ may contain <tt>?</tt> and
|
44
|
+
# +:key+ placeholders, corresponding to the additional arguments. Note
|
45
|
+
# that this behavior only applies when bind value parameters are
|
46
|
+
# supplied in the call; without them, the placeholder tokens have no
|
47
|
+
# special meaning, and will be passed through to the query as-is.
|
48
|
+
def self.sql(sql_string, *positional_binds, **named_binds)
|
49
|
+
if positional_binds.empty? && named_binds.empty?
|
50
|
+
Arel::Nodes::SqlLiteral.new sql_string
|
51
|
+
else
|
52
|
+
Arel::Nodes::BoundSqlLiteral.new sql_string, positional_binds, named_binds
|
53
|
+
end
|
39
54
|
end
|
40
55
|
|
41
56
|
def self.star # :nodoc:
|
@@ -0,0 +1,8 @@
|
|
1
|
+
Description:
|
2
|
+
Generates an `ApplicationRecord` base class for other models to inherit from.
|
3
|
+
|
4
|
+
Example:
|
5
|
+
`bin/rails generate application_record`
|
6
|
+
|
7
|
+
This generates the base class. A test is not generated because no
|
8
|
+
behaviour is included in `ApplicationRecord` by default.
|