activerecord 4.2.9 → 6.1.4.1
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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +964 -1382
- data/MIT-LICENSE +4 -2
- data/README.rdoc +15 -14
- data/examples/performance.rb +33 -32
- data/examples/simple.rb +5 -4
- data/lib/active_record/aggregations.rb +266 -251
- data/lib/active_record/association_relation.rb +40 -15
- data/lib/active_record/associations/alias_tracker.rb +40 -43
- data/lib/active_record/associations/association.rb +162 -69
- data/lib/active_record/associations/association_scope.rb +105 -130
- data/lib/active_record/associations/belongs_to_association.rb +83 -65
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
- data/lib/active_record/associations/builder/association.rb +57 -43
- data/lib/active_record/associations/builder/belongs_to.rb +74 -57
- data/lib/active_record/associations/builder/collection_association.rb +15 -37
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +49 -66
- data/lib/active_record/associations/builder/has_many.rb +13 -5
- data/lib/active_record/associations/builder/has_one.rb +44 -6
- data/lib/active_record/associations/builder/singular_association.rb +16 -10
- data/lib/active_record/associations/collection_association.rb +148 -287
- data/lib/active_record/associations/collection_proxy.rb +252 -150
- data/lib/active_record/associations/foreign_association.rb +23 -1
- data/lib/active_record/associations/has_many_association.rb +56 -98
- data/lib/active_record/associations/has_many_through_association.rb +68 -89
- data/lib/active_record/associations/has_one_association.rb +73 -47
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +54 -81
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
- data/lib/active_record/associations/join_dependency.rb +174 -169
- data/lib/active_record/associations/preloader/association.rb +108 -115
- data/lib/active_record/associations/preloader/through_association.rb +85 -65
- data/lib/active_record/associations/preloader.rb +97 -94
- data/lib/active_record/associations/singular_association.rb +18 -39
- data/lib/active_record/associations/through_association.rb +39 -19
- data/lib/active_record/associations.rb +1845 -1598
- data/lib/active_record/attribute_assignment.rb +59 -185
- data/lib/active_record/attribute_methods/before_type_cast.rb +18 -10
- data/lib/active_record/attribute_methods/dirty.rb +168 -148
- data/lib/active_record/attribute_methods/primary_key.rb +93 -83
- data/lib/active_record/attribute_methods/query.rb +8 -10
- data/lib/active_record/attribute_methods/read.rb +19 -79
- data/lib/active_record/attribute_methods/serialization.rb +49 -24
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +55 -36
- data/lib/active_record/attribute_methods/write.rb +24 -55
- data/lib/active_record/attribute_methods.rb +149 -154
- data/lib/active_record/attributes.rb +234 -78
- data/lib/active_record/autosave_association.rb +133 -60
- data/lib/active_record/base.rb +46 -46
- data/lib/active_record/callbacks.rb +234 -79
- data/lib/active_record/coders/json.rb +3 -1
- data/lib/active_record/coders/yaml_column.rb +34 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -323
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +292 -124
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
- data/lib/active_record/connection_adapters/abstract/quoting.rb +177 -60
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +8 -6
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +473 -255
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +869 -286
- data/lib/active_record/connection_adapters/abstract/transaction.rb +257 -91
- data/lib/active_record/connection_adapters/abstract_adapter.rb +483 -230
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +557 -640
- data/lib/active_record/connection_adapters/column.rb +67 -40
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +194 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +96 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +97 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +103 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +91 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +80 -192
- data/lib/active_record/connection_adapters/pool_config.rb +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +44 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +75 -160
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -58
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +8 -6
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +14 -19
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -20
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
- data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -5
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -25
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +145 -48
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +496 -298
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +588 -375
- data/lib/active_record/connection_adapters/schema_cache.rb +167 -29
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +322 -373
- data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
- data/lib/active_record/connection_adapters.rb +52 -0
- data/lib/active_record/connection_handling.rb +314 -41
- data/lib/active_record/core.rb +458 -241
- data/lib/active_record/counter_cache.rb +70 -49
- data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
- data/lib/active_record/database_configurations/database_config.rb +80 -0
- data/lib/active_record/database_configurations/hash_config.rb +96 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/database_configurations.rb +272 -0
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +87 -106
- data/lib/active_record/enum.rb +211 -92
- data/lib/active_record/errors.rb +224 -54
- data/lib/active_record/explain.rb +27 -11
- data/lib/active_record/explain_registry.rb +4 -2
- data/lib/active_record/explain_subscriber.rb +10 -5
- data/lib/active_record/fixture_set/file.rb +33 -14
- data/lib/active_record/fixture_set/model_metadata.rb +32 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +275 -500
- data/lib/active_record/gem_version.rb +6 -4
- data/lib/active_record/inheritance.rb +175 -110
- data/lib/active_record/insert_all.rb +212 -0
- data/lib/active_record/integration.rb +121 -29
- data/lib/active_record/internal_metadata.rb +62 -0
- data/lib/active_record/legacy_yaml_adapter.rb +27 -5
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +98 -92
- data/lib/active_record/locking/pessimistic.rb +22 -6
- data/lib/active_record/log_subscriber.rb +93 -31
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +77 -0
- data/lib/active_record/migration/command_recorder.rb +185 -90
- data/lib/active_record/migration/compatibility.rb +295 -0
- data/lib/active_record/migration/join_table.rb +8 -7
- data/lib/active_record/migration.rb +673 -325
- data/lib/active_record/model_schema.rb +418 -113
- data/lib/active_record/nested_attributes.rb +263 -224
- data/lib/active_record/no_touching.rb +15 -2
- data/lib/active_record/null_relation.rb +24 -38
- data/lib/active_record/persistence.rb +572 -136
- data/lib/active_record/query_cache.rb +29 -23
- data/lib/active_record/querying.rb +50 -31
- data/lib/active_record/railtie.rb +170 -51
- data/lib/active_record/railties/console_sandbox.rb +3 -3
- data/lib/active_record/railties/controller_runtime.rb +34 -33
- data/lib/active_record/railties/databases.rake +523 -199
- data/lib/active_record/readonly_attributes.rb +9 -4
- data/lib/active_record/reflection.rb +454 -291
- data/lib/active_record/relation/batches/batch_enumerator.rb +85 -0
- data/lib/active_record/relation/batches.rb +217 -59
- data/lib/active_record/relation/calculations.rb +324 -249
- data/lib/active_record/relation/delegation.rb +76 -84
- data/lib/active_record/relation/finder_methods.rb +316 -242
- data/lib/active_record/relation/from_clause.rb +30 -0
- data/lib/active_record/relation/merger.rb +95 -103
- data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -26
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +57 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
- data/lib/active_record/relation/predicate_builder.rb +136 -122
- data/lib/active_record/relation/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +757 -413
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +18 -20
- data/lib/active_record/relation/where_clause.rb +239 -0
- data/lib/active_record/relation.rb +554 -343
- data/lib/active_record/result.rb +91 -47
- data/lib/active_record/runtime_registry.rb +6 -4
- data/lib/active_record/sanitization.rb +134 -122
- data/lib/active_record/schema.rb +21 -24
- data/lib/active_record/schema_dumper.rb +141 -92
- data/lib/active_record/schema_migration.rb +24 -23
- data/lib/active_record/scoping/default.rb +96 -83
- data/lib/active_record/scoping/named.rb +78 -36
- data/lib/active_record/scoping.rb +45 -27
- data/lib/active_record/secure_token.rb +48 -0
- data/lib/active_record/serialization.rb +8 -6
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +89 -36
- data/lib/active_record/store.rb +128 -43
- data/lib/active_record/suppressor.rb +61 -0
- data/lib/active_record/table_metadata.rb +81 -0
- data/lib/active_record/tasks/database_tasks.rb +364 -130
- data/lib/active_record/tasks/mysql_database_tasks.rb +67 -113
- data/lib/active_record/tasks/postgresql_database_tasks.rb +86 -49
- data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -19
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +287 -0
- data/lib/active_record/timestamp.rb +86 -43
- data/lib/active_record/touch_later.rb +65 -0
- data/lib/active_record/transactions.rb +182 -163
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type/adapter_specific_registry.rb +126 -0
- data/lib/active_record/type/date.rb +4 -45
- data/lib/active_record/type/date_time.rb +4 -49
- data/lib/active_record/type/decimal_without_scale.rb +6 -2
- data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
- data/lib/active_record/type/internal/timezone.rb +17 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +27 -15
- data/lib/active_record/type/text.rb +2 -2
- data/lib/active_record/type/time.rb +21 -16
- data/lib/active_record/type/type_map.rb +16 -19
- data/lib/active_record/type/unsigned_integer.rb +9 -8
- data/lib/active_record/type.rb +84 -23
- data/lib/active_record/type_caster/connection.rb +33 -0
- data/lib/active_record/type_caster/map.rb +23 -0
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +12 -4
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/presence.rb +14 -13
- data/lib/active_record/validations/uniqueness.rb +63 -56
- data/lib/active_record/validations.rb +39 -35
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +42 -29
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +41 -0
- data/lib/arel/collectors/bind.rb +29 -0
- data/lib/arel/collectors/composite.rb +39 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +27 -0
- data/lib/arel/collectors/substitute_binds.rb +35 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +126 -0
- data/lib/arel/nodes/bind_param.rb +44 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +62 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +15 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +76 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +51 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +70 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +250 -0
- data/lib/arel/select_manager.rb +270 -0
- data/lib/arel/table.rb +118 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/dot.rb +308 -0
- data/lib/arel/visitors/mysql.rb +93 -0
- data/lib/arel/visitors/postgresql.rb +120 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +899 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +54 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -37
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +26 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +13 -4
- data/lib/rails/generators/active_record/migration.rb +35 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +55 -22
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- data/lib/rails/generators/active_record.rb +7 -5
- metadata +172 -65
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -24
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -23
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -21
- data/lib/active_record/attribute.rb +0 -163
- data/lib/active_record/attribute_decorators.rb +0 -66
- data/lib/active_record/attribute_set/builder.rb +0 -106
- data/lib/active_record/attribute_set.rb +0 -81
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -275
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -31
- data/lib/active_record/type/decimal.rb +0 -64
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -59
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -40
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/value.rb +0 -110
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -19
- data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
@@ -1,46 +1,38 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
# :stopdoc:
|
5
5
|
module ConnectionAdapters
|
6
6
|
# An abstract definition of a column in a table.
|
7
7
|
class Column
|
8
|
-
|
9
|
-
FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE', 'off', 'OFF'].to_set
|
8
|
+
include Deduplicable
|
10
9
|
|
11
|
-
|
12
|
-
ISO_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/
|
13
|
-
ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/
|
14
|
-
end
|
15
|
-
|
16
|
-
attr_reader :name, :cast_type, :null, :sql_type, :default, :default_function
|
10
|
+
attr_reader :name, :default, :sql_type_metadata, :null, :default_function, :collation, :comment
|
17
11
|
|
18
|
-
delegate :
|
19
|
-
:text?, :number?, :binary?, :changed?,
|
20
|
-
:type_cast_from_user, :type_cast_from_database, :type_cast_for_database,
|
21
|
-
:type_cast_for_schema,
|
22
|
-
to: :cast_type
|
12
|
+
delegate :precision, :scale, :limit, :type, :sql_type, to: :sql_type_metadata, allow_nil: true
|
23
13
|
|
24
14
|
# Instantiates a new column in the table.
|
25
15
|
#
|
26
|
-
# +name+ is the column's name, such as <tt>supplier_id</tt> in <tt>supplier_id
|
16
|
+
# +name+ is the column's name, such as <tt>supplier_id</tt> in <tt>supplier_id bigint</tt>.
|
27
17
|
# +default+ is the type-casted default value, such as +new+ in <tt>sales_stage varchar(20) default 'new'</tt>.
|
28
|
-
# +
|
29
|
-
# +sql_type+ is used to extract the column's length, if necessary. For example +60+ in
|
30
|
-
# <tt>company_name varchar(60)</tt>.
|
31
|
-
# It will be mapped to one of the standard Rails SQL types in the <tt>type</tt> attribute.
|
18
|
+
# +sql_type_metadata+ is various information about the type of the column
|
32
19
|
# +null+ determines if this column allows +NULL+ values.
|
33
|
-
def initialize(name, default,
|
34
|
-
@name
|
35
|
-
@
|
36
|
-
@
|
37
|
-
@
|
38
|
-
@
|
39
|
-
@
|
20
|
+
def initialize(name, default, sql_type_metadata = nil, null = true, default_function = nil, collation: nil, comment: nil, **)
|
21
|
+
@name = name.freeze
|
22
|
+
@sql_type_metadata = sql_type_metadata
|
23
|
+
@null = null
|
24
|
+
@default = default
|
25
|
+
@default_function = default_function
|
26
|
+
@collation = collation
|
27
|
+
@comment = comment
|
40
28
|
end
|
41
29
|
|
42
30
|
def has_default?
|
43
|
-
!default.nil?
|
31
|
+
!default.nil? || default_function
|
32
|
+
end
|
33
|
+
|
34
|
+
def bigint?
|
35
|
+
/\Abigint\b/.match?(sql_type)
|
44
36
|
end
|
45
37
|
|
46
38
|
# Returns the human name of the column name.
|
@@ -51,30 +43,65 @@ module ActiveRecord
|
|
51
43
|
Base.human_attribute_name(@name)
|
52
44
|
end
|
53
45
|
|
54
|
-
def
|
55
|
-
|
56
|
-
|
57
|
-
|
46
|
+
def init_with(coder)
|
47
|
+
@name = coder["name"]
|
48
|
+
@sql_type_metadata = coder["sql_type_metadata"]
|
49
|
+
@null = coder["null"]
|
50
|
+
@default = coder["default"]
|
51
|
+
@default_function = coder["default_function"]
|
52
|
+
@collation = coder["collation"]
|
53
|
+
@comment = coder["comment"]
|
54
|
+
end
|
55
|
+
|
56
|
+
def encode_with(coder)
|
57
|
+
coder["name"] = @name
|
58
|
+
coder["sql_type_metadata"] = @sql_type_metadata
|
59
|
+
coder["null"] = @null
|
60
|
+
coder["default"] = @default
|
61
|
+
coder["default_function"] = @default_function
|
62
|
+
coder["collation"] = @collation
|
63
|
+
coder["comment"] = @comment
|
58
64
|
end
|
59
65
|
|
60
66
|
def ==(other)
|
61
|
-
other.
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
+
other.is_a?(Column) &&
|
68
|
+
name == other.name &&
|
69
|
+
default == other.default &&
|
70
|
+
sql_type_metadata == other.sql_type_metadata &&
|
71
|
+
null == other.null &&
|
72
|
+
default_function == other.default_function &&
|
73
|
+
collation == other.collation &&
|
74
|
+
comment == other.comment
|
67
75
|
end
|
68
76
|
alias :eql? :==
|
69
77
|
|
70
78
|
def hash
|
71
|
-
|
79
|
+
Column.hash ^
|
80
|
+
name.hash ^
|
81
|
+
name.encoding.hash ^
|
82
|
+
default.hash ^
|
83
|
+
sql_type_metadata.hash ^
|
84
|
+
null.hash ^
|
85
|
+
default_function.hash ^
|
86
|
+
collation.hash ^
|
87
|
+
comment.hash
|
72
88
|
end
|
73
89
|
|
74
90
|
private
|
91
|
+
def deduplicated
|
92
|
+
@name = -name
|
93
|
+
@sql_type_metadata = sql_type_metadata.deduplicate if sql_type_metadata
|
94
|
+
@default = -default if default
|
95
|
+
@default_function = -default_function if default_function
|
96
|
+
@collation = -collation if collation
|
97
|
+
@comment = -comment if comment
|
98
|
+
super
|
99
|
+
end
|
100
|
+
end
|
75
101
|
|
76
|
-
|
77
|
-
|
102
|
+
class NullColumn < Column
|
103
|
+
def initialize(name, **)
|
104
|
+
super(name, nil)
|
78
105
|
end
|
79
106
|
end
|
80
107
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters # :nodoc:
|
5
|
+
module Deduplicable
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def registry
|
10
|
+
@registry ||= {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def new(*, **)
|
14
|
+
super.deduplicate
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def deduplicate
|
19
|
+
self.class.registry[self] ||= deduplicated
|
20
|
+
end
|
21
|
+
alias :-@ :deduplicate
|
22
|
+
|
23
|
+
private
|
24
|
+
def deduplicated
|
25
|
+
freeze
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
class LegacyPoolManager # :nodoc:
|
6
|
+
def initialize
|
7
|
+
@name_to_pool_config = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def shard_names
|
11
|
+
@name_to_pool_config.keys
|
12
|
+
end
|
13
|
+
|
14
|
+
def pool_configs(_ = nil)
|
15
|
+
@name_to_pool_config.values
|
16
|
+
end
|
17
|
+
|
18
|
+
def remove_pool_config(_, shard)
|
19
|
+
@name_to_pool_config.delete(shard)
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_pool_config(_, shard)
|
23
|
+
@name_to_pool_config[shard]
|
24
|
+
end
|
25
|
+
|
26
|
+
def set_pool_config(role, shard, pool_config)
|
27
|
+
if pool_config
|
28
|
+
@name_to_pool_config[shard] = pool_config
|
29
|
+
else
|
30
|
+
raise ArgumentError, "The `pool_config` for the :#{role} role and :#{shard} shard was `nil`. Please check your configuration. If you want your writing role to be something other than `:writing` set `config.active_record.writing_role` in your application configuration. The same setting should be applied for the `reading_role` if applicable."
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module MySQL
|
6
|
+
class Column < ConnectionAdapters::Column # :nodoc:
|
7
|
+
delegate :extra, to: :sql_type_metadata, allow_nil: true
|
8
|
+
|
9
|
+
def unsigned?
|
10
|
+
/\bunsigned(?: zerofill)?\z/.match?(sql_type)
|
11
|
+
end
|
12
|
+
|
13
|
+
def case_sensitive?
|
14
|
+
collation && !collation.end_with?("_ci")
|
15
|
+
end
|
16
|
+
|
17
|
+
def auto_increment?
|
18
|
+
extra == "auto_increment"
|
19
|
+
end
|
20
|
+
|
21
|
+
def virtual?
|
22
|
+
/\b(?:VIRTUAL|STORED|PERSISTENT)\b/.match?(extra)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,194 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module MySQL
|
6
|
+
module DatabaseStatements
|
7
|
+
# Returns an ActiveRecord::Result instance.
|
8
|
+
def select_all(*, **) # :nodoc:
|
9
|
+
result = if ExplainRegistry.collect? && prepared_statements
|
10
|
+
unprepared_statement { super }
|
11
|
+
else
|
12
|
+
super
|
13
|
+
end
|
14
|
+
@connection.abandon_results!
|
15
|
+
result
|
16
|
+
end
|
17
|
+
|
18
|
+
def query(sql, name = nil) # :nodoc:
|
19
|
+
execute(sql, name).to_a
|
20
|
+
end
|
21
|
+
|
22
|
+
READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
|
23
|
+
:desc, :describe, :set, :show, :use
|
24
|
+
) # :nodoc:
|
25
|
+
private_constant :READ_QUERY
|
26
|
+
|
27
|
+
def write_query?(sql) # :nodoc:
|
28
|
+
!READ_QUERY.match?(sql)
|
29
|
+
end
|
30
|
+
|
31
|
+
def explain(arel, binds = [])
|
32
|
+
sql = "EXPLAIN #{to_sql(arel, binds)}"
|
33
|
+
start = Concurrent.monotonic_time
|
34
|
+
result = exec_query(sql, "EXPLAIN", binds)
|
35
|
+
elapsed = Concurrent.monotonic_time - start
|
36
|
+
|
37
|
+
MySQL::ExplainPrettyPrinter.new.pp(result, elapsed)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Executes the SQL statement in the context of this connection.
|
41
|
+
def execute(sql, name = nil)
|
42
|
+
if preventing_writes? && write_query?(sql)
|
43
|
+
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
44
|
+
end
|
45
|
+
|
46
|
+
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
|
47
|
+
# made since we established the connection
|
48
|
+
@connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
|
49
|
+
|
50
|
+
super
|
51
|
+
end
|
52
|
+
|
53
|
+
def exec_query(sql, name = "SQL", binds = [], prepare: false)
|
54
|
+
if without_prepared_statement?(binds)
|
55
|
+
execute_and_free(sql, name) do |result|
|
56
|
+
if result
|
57
|
+
build_result(columns: result.fields, rows: result.to_a)
|
58
|
+
else
|
59
|
+
build_result(columns: [], rows: [])
|
60
|
+
end
|
61
|
+
end
|
62
|
+
else
|
63
|
+
exec_stmt_and_free(sql, name, binds, cache_stmt: prepare) do |_, result|
|
64
|
+
if result
|
65
|
+
build_result(columns: result.fields, rows: result.to_a)
|
66
|
+
else
|
67
|
+
build_result(columns: [], rows: [])
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def exec_delete(sql, name = nil, binds = [])
|
74
|
+
if without_prepared_statement?(binds)
|
75
|
+
@lock.synchronize do
|
76
|
+
execute_and_free(sql, name) { @connection.affected_rows }
|
77
|
+
end
|
78
|
+
else
|
79
|
+
exec_stmt_and_free(sql, name, binds) { |stmt| stmt.affected_rows }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
alias :exec_update :exec_delete
|
83
|
+
|
84
|
+
private
|
85
|
+
def execute_batch(statements, name = nil)
|
86
|
+
combine_multi_statements(statements).each do |statement|
|
87
|
+
execute(statement, name)
|
88
|
+
end
|
89
|
+
@connection.abandon_results!
|
90
|
+
end
|
91
|
+
|
92
|
+
def default_insert_value(column)
|
93
|
+
super unless column.auto_increment?
|
94
|
+
end
|
95
|
+
|
96
|
+
def last_inserted_id(result)
|
97
|
+
@connection.last_id
|
98
|
+
end
|
99
|
+
|
100
|
+
def multi_statements_enabled?
|
101
|
+
flags = @config[:flags]
|
102
|
+
|
103
|
+
if flags.is_a?(Array)
|
104
|
+
flags.include?("MULTI_STATEMENTS")
|
105
|
+
else
|
106
|
+
flags.anybits?(Mysql2::Client::MULTI_STATEMENTS)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def with_multi_statements
|
111
|
+
multi_statements_was = multi_statements_enabled?
|
112
|
+
|
113
|
+
unless multi_statements_was
|
114
|
+
@connection.set_server_option(Mysql2::Client::OPTION_MULTI_STATEMENTS_ON)
|
115
|
+
end
|
116
|
+
|
117
|
+
yield
|
118
|
+
ensure
|
119
|
+
unless multi_statements_was
|
120
|
+
@connection.set_server_option(Mysql2::Client::OPTION_MULTI_STATEMENTS_OFF)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def combine_multi_statements(total_sql)
|
125
|
+
total_sql.each_with_object([]) do |sql, total_sql_chunks|
|
126
|
+
previous_packet = total_sql_chunks.last
|
127
|
+
if max_allowed_packet_reached?(sql, previous_packet)
|
128
|
+
total_sql_chunks << +sql
|
129
|
+
else
|
130
|
+
previous_packet << ";\n"
|
131
|
+
previous_packet << sql
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def max_allowed_packet_reached?(current_packet, previous_packet)
|
137
|
+
if current_packet.bytesize > max_allowed_packet
|
138
|
+
raise ActiveRecordError,
|
139
|
+
"Fixtures set is too large #{current_packet.bytesize}. Consider increasing the max_allowed_packet variable."
|
140
|
+
elsif previous_packet.nil?
|
141
|
+
true
|
142
|
+
else
|
143
|
+
(current_packet.bytesize + previous_packet.bytesize + 2) > max_allowed_packet
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def max_allowed_packet
|
148
|
+
@max_allowed_packet ||= show_variable("max_allowed_packet")
|
149
|
+
end
|
150
|
+
|
151
|
+
def exec_stmt_and_free(sql, name, binds, cache_stmt: false)
|
152
|
+
if preventing_writes? && write_query?(sql)
|
153
|
+
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
154
|
+
end
|
155
|
+
|
156
|
+
materialize_transactions
|
157
|
+
mark_transaction_written_if_write(sql)
|
158
|
+
|
159
|
+
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
|
160
|
+
# made since we established the connection
|
161
|
+
@connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
|
162
|
+
|
163
|
+
type_casted_binds = type_casted_binds(binds)
|
164
|
+
|
165
|
+
log(sql, name, binds, type_casted_binds) do
|
166
|
+
if cache_stmt
|
167
|
+
stmt = @statements[sql] ||= @connection.prepare(sql)
|
168
|
+
else
|
169
|
+
stmt = @connection.prepare(sql)
|
170
|
+
end
|
171
|
+
|
172
|
+
begin
|
173
|
+
result = ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
174
|
+
stmt.execute(*type_casted_binds)
|
175
|
+
end
|
176
|
+
rescue Mysql2::Error => e
|
177
|
+
if cache_stmt
|
178
|
+
@statements.delete(sql)
|
179
|
+
else
|
180
|
+
stmt.close
|
181
|
+
end
|
182
|
+
raise e
|
183
|
+
end
|
184
|
+
|
185
|
+
ret = yield stmt, result
|
186
|
+
result.free if result
|
187
|
+
stmt.close unless cache_stmt
|
188
|
+
ret
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module MySQL
|
6
|
+
class ExplainPrettyPrinter # :nodoc:
|
7
|
+
# Pretty prints the result of an EXPLAIN in a way that resembles the output of the
|
8
|
+
# MySQL shell:
|
9
|
+
#
|
10
|
+
# +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
|
11
|
+
# | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|
12
|
+
# +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
|
13
|
+
# | 1 | SIMPLE | users | const | PRIMARY | PRIMARY | 4 | const | 1 | |
|
14
|
+
# | 1 | SIMPLE | posts | ALL | NULL | NULL | NULL | NULL | 1 | Using where |
|
15
|
+
# +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+
|
16
|
+
# 2 rows in set (0.00 sec)
|
17
|
+
#
|
18
|
+
# This is an exercise in Ruby hyperrealism :).
|
19
|
+
def pp(result, elapsed)
|
20
|
+
widths = compute_column_widths(result)
|
21
|
+
separator = build_separator(widths)
|
22
|
+
|
23
|
+
pp = []
|
24
|
+
|
25
|
+
pp << separator
|
26
|
+
pp << build_cells(result.columns, widths)
|
27
|
+
pp << separator
|
28
|
+
|
29
|
+
result.rows.each do |row|
|
30
|
+
pp << build_cells(row, widths)
|
31
|
+
end
|
32
|
+
|
33
|
+
pp << separator
|
34
|
+
pp << build_footer(result.rows.length, elapsed)
|
35
|
+
|
36
|
+
pp.join("\n") + "\n"
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
def compute_column_widths(result)
|
41
|
+
[].tap do |widths|
|
42
|
+
result.columns.each_with_index do |column, i|
|
43
|
+
cells_in_column = [column] + result.rows.map { |r| r[i].nil? ? "NULL" : r[i].to_s }
|
44
|
+
widths << cells_in_column.map(&:length).max
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def build_separator(widths)
|
50
|
+
padding = 1
|
51
|
+
"+" + widths.map { |w| "-" * (w + (padding * 2)) }.join("+") + "+"
|
52
|
+
end
|
53
|
+
|
54
|
+
def build_cells(items, widths)
|
55
|
+
cells = []
|
56
|
+
items.each_with_index do |item, i|
|
57
|
+
item = "NULL" if item.nil?
|
58
|
+
justifier = item.is_a?(Numeric) ? "rjust" : "ljust"
|
59
|
+
cells << item.to_s.public_send(justifier, widths[i])
|
60
|
+
end
|
61
|
+
"| " + cells.join(" | ") + " |"
|
62
|
+
end
|
63
|
+
|
64
|
+
def build_footer(nrows, elapsed)
|
65
|
+
rows_label = nrows == 1 ? "row" : "rows"
|
66
|
+
"#{nrows} #{rows_label} in set (%.2f sec)" % elapsed
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/time_with_zone"
|
4
|
+
|
5
|
+
module ActiveRecord
|
6
|
+
module ConnectionAdapters
|
7
|
+
module MySQL
|
8
|
+
module Quoting # :nodoc:
|
9
|
+
def quote_column_name(name)
|
10
|
+
self.class.quoted_column_names[name] ||= "`#{super.gsub('`', '``')}`"
|
11
|
+
end
|
12
|
+
|
13
|
+
def quote_table_name(name)
|
14
|
+
self.class.quoted_table_names[name] ||= super.gsub(".", "`.`").freeze
|
15
|
+
end
|
16
|
+
|
17
|
+
def unquoted_true
|
18
|
+
1
|
19
|
+
end
|
20
|
+
|
21
|
+
def unquoted_false
|
22
|
+
0
|
23
|
+
end
|
24
|
+
|
25
|
+
def quoted_date(value)
|
26
|
+
if supports_datetime_with_precision?
|
27
|
+
super
|
28
|
+
else
|
29
|
+
super.sub(/\.\d{6}\z/, "")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def quoted_binary(value)
|
34
|
+
"x'#{value.hex}'"
|
35
|
+
end
|
36
|
+
|
37
|
+
def column_name_matcher
|
38
|
+
COLUMN_NAME
|
39
|
+
end
|
40
|
+
|
41
|
+
def column_name_with_order_matcher
|
42
|
+
COLUMN_NAME_WITH_ORDER
|
43
|
+
end
|
44
|
+
|
45
|
+
COLUMN_NAME = /
|
46
|
+
\A
|
47
|
+
(
|
48
|
+
(?:
|
49
|
+
# `table_name`.`column_name` | function(one or no argument)
|
50
|
+
((?:\w+\.|`\w+`\.)?(?:\w+|`\w+`)) | \w+\((?:|\g<2>)\)
|
51
|
+
)
|
52
|
+
(?:(?:\s+AS)?\s+(?:\w+|`\w+`))?
|
53
|
+
)
|
54
|
+
(?:\s*,\s*\g<1>)*
|
55
|
+
\z
|
56
|
+
/ix
|
57
|
+
|
58
|
+
COLUMN_NAME_WITH_ORDER = /
|
59
|
+
\A
|
60
|
+
(
|
61
|
+
(?:
|
62
|
+
# `table_name`.`column_name` | function(one or no argument)
|
63
|
+
((?:\w+\.|`\w+`\.)?(?:\w+|`\w+`)) | \w+\((?:|\g<2>)\)
|
64
|
+
)
|
65
|
+
(?:\s+ASC|\s+DESC)?
|
66
|
+
)
|
67
|
+
(?:\s*,\s*\g<1>)*
|
68
|
+
\z
|
69
|
+
/ix
|
70
|
+
|
71
|
+
private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
|
72
|
+
|
73
|
+
private
|
74
|
+
# Override +_type_cast+ we pass to mysql2 Date and Time objects instead
|
75
|
+
# of Strings since mysql2 is able to handle those classes more efficiently.
|
76
|
+
def _type_cast(value)
|
77
|
+
case value
|
78
|
+
when ActiveSupport::TimeWithZone
|
79
|
+
# We need to check explicitly for ActiveSupport::TimeWithZone because
|
80
|
+
# we need to transform it to Time objects but we don't want to
|
81
|
+
# transform Time objects to themselves.
|
82
|
+
if ActiveRecord::Base.default_timezone == :utc
|
83
|
+
value.getutc
|
84
|
+
else
|
85
|
+
value.getlocal
|
86
|
+
end
|
87
|
+
when Date, Time
|
88
|
+
value
|
89
|
+
else
|
90
|
+
super
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module MySQL
|
6
|
+
class SchemaCreation < SchemaCreation # :nodoc:
|
7
|
+
delegate :add_sql_comment!, :mariadb?, to: :@conn, private: true
|
8
|
+
|
9
|
+
private
|
10
|
+
def visit_DropForeignKey(name)
|
11
|
+
"DROP FOREIGN KEY #{name}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def visit_DropCheckConstraint(name)
|
15
|
+
"DROP #{mariadb? ? 'CONSTRAINT' : 'CHECK'} #{name}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def visit_AddColumnDefinition(o)
|
19
|
+
add_column_position!(super, column_options(o.column))
|
20
|
+
end
|
21
|
+
|
22
|
+
def visit_ChangeColumnDefinition(o)
|
23
|
+
change_column_sql = +"CHANGE #{quote_column_name(o.name)} #{accept(o.column)}"
|
24
|
+
add_column_position!(change_column_sql, column_options(o.column))
|
25
|
+
end
|
26
|
+
|
27
|
+
def visit_CreateIndexDefinition(o)
|
28
|
+
sql = visit_IndexDefinition(o.index, true)
|
29
|
+
sql << " #{o.algorithm}" if o.algorithm
|
30
|
+
sql
|
31
|
+
end
|
32
|
+
|
33
|
+
def visit_IndexDefinition(o, create = false)
|
34
|
+
index_type = o.type&.to_s&.upcase || o.unique && "UNIQUE"
|
35
|
+
|
36
|
+
sql = create ? ["CREATE"] : []
|
37
|
+
sql << index_type if index_type
|
38
|
+
sql << "INDEX"
|
39
|
+
sql << quote_column_name(o.name)
|
40
|
+
sql << "USING #{o.using}" if o.using
|
41
|
+
sql << "ON #{quote_table_name(o.table)}" if create
|
42
|
+
sql << "(#{quoted_columns(o)})"
|
43
|
+
|
44
|
+
add_sql_comment!(sql.join(" "), o.comment)
|
45
|
+
end
|
46
|
+
|
47
|
+
def add_table_options!(create_sql, o)
|
48
|
+
create_sql << " DEFAULT CHARSET=#{o.charset}" if o.charset
|
49
|
+
create_sql << " COLLATE=#{o.collation}" if o.collation
|
50
|
+
add_sql_comment!(super, o.comment)
|
51
|
+
end
|
52
|
+
|
53
|
+
def add_column_options!(sql, options)
|
54
|
+
# By default, TIMESTAMP columns are NOT NULL, cannot contain NULL values,
|
55
|
+
# and assigning NULL assigns the current timestamp. To permit a TIMESTAMP
|
56
|
+
# column to contain NULL, explicitly declare it with the NULL attribute.
|
57
|
+
# See https://dev.mysql.com/doc/refman/en/timestamp-initialization.html
|
58
|
+
if /\Atimestamp\b/.match?(options[:column].sql_type) && !options[:primary_key]
|
59
|
+
sql << " NULL" unless options[:null] == false || options_include_default?(options)
|
60
|
+
end
|
61
|
+
|
62
|
+
if charset = options[:charset]
|
63
|
+
sql << " CHARACTER SET #{charset}"
|
64
|
+
end
|
65
|
+
|
66
|
+
if collation = options[:collation]
|
67
|
+
sql << " COLLATE #{collation}"
|
68
|
+
end
|
69
|
+
|
70
|
+
if as = options[:as]
|
71
|
+
sql << " AS (#{as})"
|
72
|
+
if options[:stored]
|
73
|
+
sql << (mariadb? ? " PERSISTENT" : " STORED")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
add_sql_comment!(super, options[:comment])
|
78
|
+
end
|
79
|
+
|
80
|
+
def add_column_position!(sql, options)
|
81
|
+
if options[:first]
|
82
|
+
sql << " FIRST"
|
83
|
+
elsif options[:after]
|
84
|
+
sql << " AFTER #{quote_column_name(options[:after])}"
|
85
|
+
end
|
86
|
+
|
87
|
+
sql
|
88
|
+
end
|
89
|
+
|
90
|
+
def index_in_create(table_name, column_name, options)
|
91
|
+
index, _ = @conn.add_index_options(table_name, column_name, **options)
|
92
|
+
accept(index)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|