activerecord 3.2.6 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/CHANGELOG.md +611 -6417
- data/MIT-LICENSE +4 -2
- data/README.rdoc +44 -47
- data/examples/performance.rb +79 -71
- data/examples/simple.rb +6 -5
- data/lib/active_record/aggregations.rb +268 -238
- data/lib/active_record/association_relation.rb +40 -0
- data/lib/active_record/associations/alias_tracker.rb +47 -42
- data/lib/active_record/associations/association.rb +173 -81
- data/lib/active_record/associations/association_scope.rb +124 -92
- data/lib/active_record/associations/belongs_to_association.rb +83 -38
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +11 -9
- data/lib/active_record/associations/builder/association.rb +113 -32
- data/lib/active_record/associations/builder/belongs_to.rb +105 -60
- data/lib/active_record/associations/builder/collection_association.rb +53 -56
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +98 -41
- data/lib/active_record/associations/builder/has_many.rb +11 -63
- data/lib/active_record/associations/builder/has_one.rb +47 -45
- data/lib/active_record/associations/builder/singular_association.rb +30 -18
- data/lib/active_record/associations/collection_association.rb +217 -295
- data/lib/active_record/associations/collection_proxy.rb +1074 -77
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +78 -50
- data/lib/active_record/associations/has_many_through_association.rb +99 -61
- data/lib/active_record/associations/has_one_association.rb +75 -30
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +45 -119
- data/lib/active_record/associations/join_dependency/join_base.rb +11 -12
- data/lib/active_record/associations/join_dependency/join_part.rb +35 -42
- data/lib/active_record/associations/join_dependency.rb +208 -164
- data/lib/active_record/associations/preloader/association.rb +93 -87
- data/lib/active_record/associations/preloader/through_association.rb +87 -38
- data/lib/active_record/associations/preloader.rb +134 -110
- data/lib/active_record/associations/singular_association.rb +19 -24
- data/lib/active_record/associations/through_association.rb +61 -27
- data/lib/active_record/associations.rb +1766 -1505
- data/lib/active_record/attribute_assignment.rb +57 -193
- data/lib/active_record/attribute_decorators.rb +90 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +58 -8
- data/lib/active_record/attribute_methods/dirty.rb +187 -67
- data/lib/active_record/attribute_methods/primary_key.rb +100 -78
- data/lib/active_record/attribute_methods/query.rb +10 -8
- data/lib/active_record/attribute_methods/read.rb +29 -118
- data/lib/active_record/attribute_methods/serialization.rb +60 -72
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +69 -42
- data/lib/active_record/attribute_methods/write.rb +36 -44
- data/lib/active_record/attribute_methods.rb +306 -161
- data/lib/active_record/attributes.rb +279 -0
- data/lib/active_record/autosave_association.rb +324 -238
- data/lib/active_record/base.rb +114 -507
- data/lib/active_record/callbacks.rb +147 -83
- data/lib/active_record/coders/json.rb +15 -0
- data/lib/active_record/coders/yaml_column.rb +32 -23
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +962 -279
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +32 -5
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +331 -209
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +95 -23
- data/lib/active_record/connection_adapters/abstract/quoting.rb +201 -65
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +510 -289
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +93 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1182 -313
- data/lib/active_record/connection_adapters/abstract/transaction.rb +323 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +585 -120
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +610 -463
- data/lib/active_record/connection_adapters/column.rb +58 -233
- data/lib/active_record/connection_adapters/connection_specification.rb +297 -0
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +200 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +75 -207
- data/lib/active_record/connection_adapters/postgresql/column.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +182 -0
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +92 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +53 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +41 -0
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +113 -0
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +26 -0
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +205 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +222 -0
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +776 -0
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +695 -1052
- data/lib/active_record/connection_adapters/schema_cache.rb +115 -24
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +103 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -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 +137 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +528 -26
- data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
- data/lib/active_record/connection_handling.rb +267 -0
- data/lib/active_record/core.rb +599 -0
- data/lib/active_record/counter_cache.rb +177 -103
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +79 -0
- data/lib/active_record/database_configurations.rb +233 -0
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +107 -64
- data/lib/active_record/enum.rb +274 -0
- data/lib/active_record/errors.rb +254 -61
- data/lib/active_record/explain.rb +35 -70
- data/lib/active_record/explain_registry.rb +32 -0
- data/lib/active_record/explain_subscriber.rb +18 -8
- data/lib/active_record/fixture_set/file.rb +82 -0
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +291 -475
- data/lib/active_record/gem_version.rb +17 -0
- data/lib/active_record/inheritance.rb +219 -100
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +175 -17
- data/lib/active_record/internal_metadata.rb +53 -0
- data/lib/active_record/legacy_yaml_adapter.rb +48 -0
- data/lib/active_record/locale/en.yml +9 -1
- data/lib/active_record/locking/optimistic.rb +106 -92
- data/lib/active_record/locking/pessimistic.rb +23 -11
- data/lib/active_record/log_subscriber.rb +80 -30
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +75 -0
- data/lib/active_record/migration/command_recorder.rb +235 -56
- data/lib/active_record/migration/compatibility.rb +244 -0
- data/lib/active_record/migration/join_table.rb +17 -0
- data/lib/active_record/migration.rb +917 -301
- data/lib/active_record/model_schema.rb +351 -175
- data/lib/active_record/nested_attributes.rb +366 -235
- data/lib/active_record/no_touching.rb +65 -0
- data/lib/active_record/null_relation.rb +68 -0
- data/lib/active_record/persistence.rb +761 -166
- data/lib/active_record/query_cache.rb +22 -44
- data/lib/active_record/querying.rb +55 -31
- data/lib/active_record/railtie.rb +185 -47
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/console_sandbox.rb +5 -4
- data/lib/active_record/railties/controller_runtime.rb +35 -33
- data/lib/active_record/railties/databases.rake +366 -463
- data/lib/active_record/readonly_attributes.rb +4 -6
- data/lib/active_record/reflection.rb +736 -228
- data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
- data/lib/active_record/relation/batches.rb +252 -52
- data/lib/active_record/relation/calculations.rb +340 -270
- data/lib/active_record/relation/delegation.rb +117 -36
- data/lib/active_record/relation/finder_methods.rb +439 -286
- data/lib/active_record/relation/from_clause.rb +26 -0
- data/lib/active_record/relation/merger.rb +184 -0
- data/lib/active_record/relation/predicate_builder/array_handler.rb +49 -0
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -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 +53 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder.rb +131 -39
- data/lib/active_record/relation/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +1163 -221
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +49 -120
- data/lib/active_record/relation/where_clause.rb +190 -0
- data/lib/active_record/relation/where_clause_factory.rb +33 -0
- data/lib/active_record/relation.rb +671 -349
- data/lib/active_record/result.rb +149 -15
- data/lib/active_record/runtime_registry.rb +24 -0
- data/lib/active_record/sanitization.rb +153 -133
- data/lib/active_record/schema.rb +22 -19
- data/lib/active_record/schema_dumper.rb +178 -112
- data/lib/active_record/schema_migration.rb +60 -0
- data/lib/active_record/scoping/default.rb +107 -98
- data/lib/active_record/scoping/named.rb +130 -115
- data/lib/active_record/scoping.rb +77 -123
- data/lib/active_record/secure_token.rb +40 -0
- data/lib/active_record/serialization.rb +10 -6
- data/lib/active_record/statement_cache.rb +148 -0
- data/lib/active_record/store.rb +256 -16
- data/lib/active_record/suppressor.rb +61 -0
- data/lib/active_record/table_metadata.rb +75 -0
- data/lib/active_record/tasks/database_tasks.rb +506 -0
- data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
- data/lib/active_record/tasks/postgresql_database_tasks.rb +141 -0
- data/lib/active_record/tasks/sqlite_database_tasks.rb +77 -0
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +93 -39
- data/lib/active_record/touch_later.rb +66 -0
- data/lib/active_record/transactions.rb +260 -129
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type/adapter_specific_registry.rb +129 -0
- data/lib/active_record/type/date.rb +9 -0
- data/lib/active_record/type/date_time.rb +9 -0
- data/lib/active_record/type/decimal_without_scale.rb +15 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
- 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 +71 -0
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +21 -0
- data/lib/active_record/type/type_map.rb +62 -0
- data/lib/active_record/type/unsigned_integer.rb +17 -0
- data/lib/active_record/type.rb +78 -0
- data/lib/active_record/type_caster/connection.rb +34 -0
- data/lib/active_record/type_caster/map.rb +20 -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 +35 -18
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/presence.rb +68 -0
- data/lib/active_record/validations/uniqueness.rb +123 -77
- data/lib/active_record/validations.rb +54 -43
- data/lib/active_record/version.rb +7 -7
- data/lib/active_record.rb +97 -49
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -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 +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -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 +18 -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 +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -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 +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -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 +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +45 -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 +68 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/depth_first.rb +204 -0
- data/lib/arel/visitors/dot.rb +297 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +157 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +66 -0
- data/lib/arel/visitors/postgresql.rb +110 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +889 -0
- data/lib/arel/visitors/visitor.rb +46 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +51 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -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 +59 -9
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +48 -0
- data/lib/rails/generators/active_record/migration.rb +41 -8
- data/lib/rails/generators/active_record/model/model_generator.rb +24 -22
- 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} +1 -1
- data/lib/rails/generators/active_record.rb +10 -16
- metadata +285 -149
- data/examples/associations.png +0 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -63
- data/lib/active_record/associations/join_helper.rb +0 -55
- 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_and_belongs_to_many.rb +0 -60
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -15
- 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_methods/deprecated_underscore_read.rb +0 -32
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -188
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -426
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -579
- data/lib/active_record/dynamic_finder_match.rb +0 -68
- data/lib/active_record/dynamic_scope_match.rb +0 -23
- data/lib/active_record/fixtures/file.rb +0 -65
- data/lib/active_record/identity_map.rb +0 -162
- data/lib/active_record/observer.rb +0 -121
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/serializers/xml_serializer.rb +0 -203
- data/lib/active_record/session_store.rb +0 -358
- data/lib/active_record/test_case.rb +0 -73
- data/lib/rails/generators/active_record/migration/templates/migration.rb +0 -34
- data/lib/rails/generators/active_record/model/templates/migration.rb +0 -15
- data/lib/rails/generators/active_record/model/templates/model.rb +0 -12
- data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
- data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
- data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -1,124 +1,196 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters # :nodoc:
|
3
5
|
module DatabaseStatements
|
6
|
+
def initialize
|
7
|
+
super
|
8
|
+
reset_transaction
|
9
|
+
end
|
10
|
+
|
4
11
|
# Converts an arel AST to SQL
|
5
|
-
def to_sql(
|
6
|
-
|
7
|
-
|
8
|
-
|
12
|
+
def to_sql(arel_or_sql_string, binds = [])
|
13
|
+
sql, _ = to_sql_and_binds(arel_or_sql_string, binds)
|
14
|
+
sql
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_sql_and_binds(arel_or_sql_string, binds = []) # :nodoc:
|
18
|
+
if arel_or_sql_string.respond_to?(:ast)
|
19
|
+
unless binds.empty?
|
20
|
+
raise "Passing bind parameters with an arel AST is forbidden. " \
|
21
|
+
"The values must be stored on the AST directly"
|
22
|
+
end
|
23
|
+
|
24
|
+
if prepared_statements
|
25
|
+
sql, binds = visitor.compile(arel_or_sql_string.ast, collector)
|
26
|
+
|
27
|
+
if binds.length > bind_params_length
|
28
|
+
unprepared_statement do
|
29
|
+
sql, binds = to_sql_and_binds(arel_or_sql_string)
|
30
|
+
visitor.preparable = false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
else
|
34
|
+
sql = visitor.compile(arel_or_sql_string.ast, collector)
|
9
35
|
end
|
36
|
+
[sql.freeze, binds]
|
37
|
+
else
|
38
|
+
visitor.preparable = false if prepared_statements
|
39
|
+
[arel_or_sql_string.dup.freeze, binds]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
private :to_sql_and_binds
|
43
|
+
|
44
|
+
# This is used in the StatementCache object. It returns an object that
|
45
|
+
# can be used to query the database repeatedly.
|
46
|
+
def cacheable_query(klass, arel) # :nodoc:
|
47
|
+
if prepared_statements
|
48
|
+
sql, binds = visitor.compile(arel.ast, collector)
|
49
|
+
query = klass.query(sql)
|
10
50
|
else
|
11
|
-
|
51
|
+
collector = klass.partial_query_collector
|
52
|
+
parts, binds = visitor.compile(arel.ast, collector)
|
53
|
+
query = klass.partial_query(parts)
|
12
54
|
end
|
55
|
+
[query, binds]
|
13
56
|
end
|
14
57
|
|
15
|
-
# Returns an
|
16
|
-
|
17
|
-
|
18
|
-
|
58
|
+
# Returns an ActiveRecord::Result instance.
|
59
|
+
def select_all(arel, name = nil, binds = [], preparable: nil)
|
60
|
+
arel = arel_from_relation(arel)
|
61
|
+
sql, binds = to_sql_and_binds(arel, binds)
|
62
|
+
|
63
|
+
if preparable.nil?
|
64
|
+
preparable = prepared_statements ? visitor.preparable : false
|
65
|
+
end
|
66
|
+
|
67
|
+
if prepared_statements && preparable
|
68
|
+
select_prepared(sql, name, binds)
|
69
|
+
else
|
70
|
+
select(sql, name, binds)
|
71
|
+
end
|
19
72
|
end
|
20
73
|
|
21
74
|
# Returns a record hash with the column names as keys and column values
|
22
75
|
# as values.
|
23
|
-
def select_one(arel, name = nil)
|
24
|
-
|
25
|
-
result.first if result
|
76
|
+
def select_one(arel, name = nil, binds = [])
|
77
|
+
select_all(arel, name, binds).first
|
26
78
|
end
|
27
79
|
|
28
80
|
# Returns a single value from a record
|
29
|
-
def select_value(arel, name = nil)
|
30
|
-
|
31
|
-
result.values.first
|
32
|
-
end
|
81
|
+
def select_value(arel, name = nil, binds = [])
|
82
|
+
single_value_from_rows(select_rows(arel, name, binds))
|
33
83
|
end
|
34
84
|
|
35
85
|
# Returns an array of the values of the first column in a select:
|
36
86
|
# select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
|
37
|
-
def select_values(arel, name = nil)
|
38
|
-
|
39
|
-
result.map { |v| v[0] }
|
87
|
+
def select_values(arel, name = nil, binds = [])
|
88
|
+
select_rows(arel, name, binds).map(&:first)
|
40
89
|
end
|
41
90
|
|
42
91
|
# Returns an array of arrays containing the field values.
|
43
92
|
# Order is the same as that returned by +columns+.
|
44
|
-
def select_rows(
|
93
|
+
def select_rows(arel, name = nil, binds = [])
|
94
|
+
select_all(arel, name, binds).rows
|
95
|
+
end
|
96
|
+
|
97
|
+
def query_value(sql, name = nil) # :nodoc:
|
98
|
+
single_value_from_rows(query(sql, name))
|
99
|
+
end
|
100
|
+
|
101
|
+
def query_values(sql, name = nil) # :nodoc:
|
102
|
+
query(sql, name).map(&:first)
|
45
103
|
end
|
46
|
-
undef_method :select_rows
|
47
104
|
|
48
|
-
|
105
|
+
def query(sql, name = nil) # :nodoc:
|
106
|
+
exec_query(sql, name).rows
|
107
|
+
end
|
108
|
+
|
109
|
+
# Determines whether the SQL statement is a write query.
|
110
|
+
def write_query?(sql)
|
111
|
+
raise NotImplementedError
|
112
|
+
end
|
113
|
+
|
114
|
+
# Executes the SQL statement in the context of this connection and returns
|
115
|
+
# the raw result from the connection adapter.
|
116
|
+
# Note: depending on your database connector, the result returned by this
|
117
|
+
# method may be manually memory managed. Consider using the exec_query
|
118
|
+
# wrapper instead.
|
49
119
|
def execute(sql, name = nil)
|
120
|
+
raise NotImplementedError
|
50
121
|
end
|
51
|
-
undef_method :execute
|
52
122
|
|
53
123
|
# Executes +sql+ statement in the context of this connection using
|
54
124
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
55
125
|
# the executed +sql+ statement.
|
56
|
-
def exec_query(sql, name =
|
126
|
+
def exec_query(sql, name = "SQL", binds = [], prepare: false)
|
127
|
+
raise NotImplementedError
|
57
128
|
end
|
58
129
|
|
59
130
|
# Executes insert +sql+ statement in the context of this connection using
|
60
|
-
# +binds+ as the bind substitutes. +name+ is
|
131
|
+
# +binds+ as the bind substitutes. +name+ is logged along with
|
61
132
|
# the executed +sql+ statement.
|
62
|
-
def exec_insert(sql, name, binds)
|
133
|
+
def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
|
134
|
+
sql, binds = sql_for_insert(sql, pk, binds)
|
63
135
|
exec_query(sql, name, binds)
|
64
136
|
end
|
65
137
|
|
66
138
|
# Executes delete +sql+ statement in the context of this connection using
|
67
|
-
# +binds+ as the bind substitutes. +name+ is
|
139
|
+
# +binds+ as the bind substitutes. +name+ is logged along with
|
68
140
|
# the executed +sql+ statement.
|
69
|
-
def exec_delete(sql, name, binds)
|
141
|
+
def exec_delete(sql, name = nil, binds = [])
|
70
142
|
exec_query(sql, name, binds)
|
71
143
|
end
|
72
144
|
|
73
145
|
# Executes update +sql+ statement in the context of this connection using
|
74
|
-
# +binds+ as the bind substitutes. +name+ is
|
146
|
+
# +binds+ as the bind substitutes. +name+ is logged along with
|
75
147
|
# the executed +sql+ statement.
|
76
|
-
def exec_update(sql, name, binds)
|
148
|
+
def exec_update(sql, name = nil, binds = [])
|
77
149
|
exec_query(sql, name, binds)
|
78
150
|
end
|
79
151
|
|
80
|
-
#
|
152
|
+
# Executes an INSERT query and returns the new record's ID
|
81
153
|
#
|
82
|
-
# +id_value+ will be returned unless the value is nil
|
154
|
+
# +id_value+ will be returned unless the value is +nil+, in
|
83
155
|
# which case the database will attempt to calculate the last inserted
|
84
156
|
# id and return that value.
|
85
157
|
#
|
86
158
|
# If the next id was calculated in advance (as in Oracle), it should be
|
87
159
|
# passed in as +id_value+.
|
88
160
|
def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
|
89
|
-
sql, binds =
|
90
|
-
value
|
161
|
+
sql, binds = to_sql_and_binds(arel, binds)
|
162
|
+
value = exec_insert(sql, name, binds, pk, sequence_name)
|
91
163
|
id_value || last_inserted_id(value)
|
92
164
|
end
|
165
|
+
alias create insert
|
93
166
|
|
94
167
|
# Executes the update statement and returns the number of rows affected.
|
95
168
|
def update(arel, name = nil, binds = [])
|
96
|
-
|
169
|
+
sql, binds = to_sql_and_binds(arel, binds)
|
170
|
+
exec_update(sql, name, binds)
|
97
171
|
end
|
98
172
|
|
99
173
|
# Executes the delete statement and returns the number of rows affected.
|
100
174
|
def delete(arel, name = nil, binds = [])
|
101
|
-
|
175
|
+
sql, binds = to_sql_and_binds(arel, binds)
|
176
|
+
exec_delete(sql, name, binds)
|
102
177
|
end
|
103
178
|
|
104
|
-
#
|
105
|
-
|
106
|
-
|
107
|
-
# friends.
|
108
|
-
#
|
109
|
-
# Returns true if there is no transaction active, false if there is a
|
110
|
-
# transaction active, and nil if this information is unknown.
|
111
|
-
#
|
112
|
-
# Not all adapters supports transaction state introspection. Currently,
|
113
|
-
# only the PostgreSQL adapter supports this.
|
114
|
-
def outside_transaction?
|
115
|
-
nil
|
179
|
+
# Executes the truncate statement.
|
180
|
+
def truncate(table_name, name = nil)
|
181
|
+
execute(build_truncate_statements(table_name), name)
|
116
182
|
end
|
117
183
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
184
|
+
def truncate_tables(*table_names) # :nodoc:
|
185
|
+
return if table_names.empty?
|
186
|
+
|
187
|
+
with_multi_statements do
|
188
|
+
disable_referential_integrity do
|
189
|
+
Array(build_truncate_statements(*table_names)).each do |sql|
|
190
|
+
execute_batch(sql, "Truncate Tables")
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
122
194
|
end
|
123
195
|
|
124
196
|
# Runs the given block in a database transaction, and returns the result
|
@@ -132,8 +204,9 @@ module ActiveRecord
|
|
132
204
|
#
|
133
205
|
# In order to get around this problem, #transaction will emulate the effect
|
134
206
|
# of nested transactions, by using savepoints:
|
135
|
-
#
|
136
|
-
# Savepoints are supported by MySQL and PostgreSQL
|
207
|
+
# https://dev.mysql.com/doc/refman/5.7/en/savepoint.html
|
208
|
+
# Savepoints are supported by MySQL and PostgreSQL. SQLite3 version >= '3.6.8'
|
209
|
+
# supports savepoints.
|
137
210
|
#
|
138
211
|
# It is safe to call this method if a database transaction is already open,
|
139
212
|
# i.e. if #transaction is called within another #transaction block. In case
|
@@ -158,101 +231,112 @@ module ActiveRecord
|
|
158
231
|
# already-automatically-released savepoints:
|
159
232
|
#
|
160
233
|
# Model.connection.transaction do # BEGIN
|
161
|
-
# Model.connection.transaction(:
|
234
|
+
# Model.connection.transaction(requires_new: true) do # CREATE SAVEPOINT active_record_1
|
162
235
|
# Model.connection.create_table(...)
|
163
236
|
# # active_record_1 now automatically released
|
164
237
|
# end # RELEASE SAVEPOINT active_record_1 <--- BOOM! database error!
|
165
238
|
# end
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
else
|
202
|
-
rollback_to_savepoint
|
203
|
-
rollback_transaction_records(false)
|
204
|
-
end
|
205
|
-
end
|
206
|
-
raise unless database_transaction_rollback.is_a?(ActiveRecord::Rollback)
|
207
|
-
end
|
208
|
-
ensure
|
209
|
-
@transaction_joinable = last_transaction_joinable
|
210
|
-
|
211
|
-
if outside_transaction?
|
212
|
-
@open_transactions = 0
|
213
|
-
elsif transaction_open
|
214
|
-
decrement_open_transactions
|
215
|
-
begin
|
216
|
-
if open_transactions == 0
|
217
|
-
commit_db_transaction
|
218
|
-
commit_transaction_records
|
219
|
-
else
|
220
|
-
release_savepoint
|
221
|
-
save_point_records = @_current_transaction_records.pop
|
222
|
-
unless save_point_records.blank?
|
223
|
-
@_current_transaction_records.push([]) if @_current_transaction_records.empty?
|
224
|
-
@_current_transaction_records.last.concat(save_point_records)
|
225
|
-
end
|
226
|
-
end
|
227
|
-
rescue Exception => database_transaction_rollback
|
228
|
-
if open_transactions == 0
|
229
|
-
rollback_db_transaction
|
230
|
-
rollback_transaction_records(true)
|
231
|
-
else
|
232
|
-
rollback_to_savepoint
|
233
|
-
rollback_transaction_records(false)
|
234
|
-
end
|
235
|
-
raise
|
239
|
+
#
|
240
|
+
# == Transaction isolation
|
241
|
+
#
|
242
|
+
# If your database supports setting the isolation level for a transaction, you can set
|
243
|
+
# it like so:
|
244
|
+
#
|
245
|
+
# Post.transaction(isolation: :serializable) do
|
246
|
+
# # ...
|
247
|
+
# end
|
248
|
+
#
|
249
|
+
# Valid isolation levels are:
|
250
|
+
#
|
251
|
+
# * <tt>:read_uncommitted</tt>
|
252
|
+
# * <tt>:read_committed</tt>
|
253
|
+
# * <tt>:repeatable_read</tt>
|
254
|
+
# * <tt>:serializable</tt>
|
255
|
+
#
|
256
|
+
# You should consult the documentation for your database to understand the
|
257
|
+
# semantics of these different levels:
|
258
|
+
#
|
259
|
+
# * https://www.postgresql.org/docs/current/static/transaction-iso.html
|
260
|
+
# * https://dev.mysql.com/doc/refman/5.7/en/set-transaction.html
|
261
|
+
#
|
262
|
+
# An ActiveRecord::TransactionIsolationError will be raised if:
|
263
|
+
#
|
264
|
+
# * The adapter does not support setting the isolation level
|
265
|
+
# * You are joining an existing open transaction
|
266
|
+
# * You are creating a nested (savepoint) transaction
|
267
|
+
#
|
268
|
+
# The mysql2 and postgresql adapters support setting the transaction
|
269
|
+
# isolation level.
|
270
|
+
def transaction(requires_new: nil, isolation: nil, joinable: true)
|
271
|
+
if !requires_new && current_transaction.joinable?
|
272
|
+
if isolation
|
273
|
+
raise ActiveRecord::TransactionIsolationError, "cannot set isolation when joining a transaction"
|
236
274
|
end
|
275
|
+
yield
|
276
|
+
else
|
277
|
+
transaction_manager.within_new_transaction(isolation: isolation, joinable: joinable) { yield }
|
237
278
|
end
|
279
|
+
rescue ActiveRecord::Rollback
|
280
|
+
# rollbacks are silently swallowed
|
281
|
+
end
|
282
|
+
|
283
|
+
attr_reader :transaction_manager #:nodoc:
|
284
|
+
|
285
|
+
delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction,
|
286
|
+
:commit_transaction, :rollback_transaction, :materialize_transactions,
|
287
|
+
:disable_lazy_transactions!, :enable_lazy_transactions!, to: :transaction_manager
|
288
|
+
|
289
|
+
def transaction_open?
|
290
|
+
current_transaction.open?
|
291
|
+
end
|
292
|
+
|
293
|
+
def reset_transaction #:nodoc:
|
294
|
+
@transaction_manager = ConnectionAdapters::TransactionManager.new(self)
|
238
295
|
end
|
239
296
|
|
240
297
|
# Register a record with the current transaction so that its after_commit and after_rollback callbacks
|
241
298
|
# can be called.
|
242
299
|
def add_transaction_record(record)
|
243
|
-
|
244
|
-
|
300
|
+
current_transaction.add_record(record)
|
301
|
+
end
|
302
|
+
|
303
|
+
def transaction_state
|
304
|
+
current_transaction.state
|
245
305
|
end
|
246
306
|
|
247
307
|
# Begins the transaction (and turns off auto-committing).
|
248
308
|
def begin_db_transaction() end
|
249
309
|
|
310
|
+
def transaction_isolation_levels
|
311
|
+
{
|
312
|
+
read_uncommitted: "READ UNCOMMITTED",
|
313
|
+
read_committed: "READ COMMITTED",
|
314
|
+
repeatable_read: "REPEATABLE READ",
|
315
|
+
serializable: "SERIALIZABLE"
|
316
|
+
}
|
317
|
+
end
|
318
|
+
|
319
|
+
# Begins the transaction with the isolation level set. Raises an error by
|
320
|
+
# default; adapters that support setting the isolation level should implement
|
321
|
+
# this method.
|
322
|
+
def begin_isolated_db_transaction(isolation)
|
323
|
+
raise ActiveRecord::TransactionIsolationError, "adapter does not support setting transaction isolation"
|
324
|
+
end
|
325
|
+
|
250
326
|
# Commits the transaction (and turns on auto-committing).
|
251
327
|
def commit_db_transaction() end
|
252
328
|
|
253
329
|
# Rolls back the transaction (and turns on auto-committing). Must be
|
254
330
|
# done if the transaction block raises an exception or returns false.
|
255
|
-
def rollback_db_transaction
|
331
|
+
def rollback_db_transaction
|
332
|
+
exec_rollback_db_transaction
|
333
|
+
end
|
334
|
+
|
335
|
+
def exec_rollback_db_transaction() end #:nodoc:
|
336
|
+
|
337
|
+
def rollback_to_savepoint(name = nil)
|
338
|
+
exec_rollback_to_savepoint(name)
|
339
|
+
end
|
256
340
|
|
257
341
|
def default_sequence_name(table, column)
|
258
342
|
nil
|
@@ -265,126 +349,164 @@ module ActiveRecord
|
|
265
349
|
|
266
350
|
# Inserts the given fixture into the table. Overridden in adapters that require
|
267
351
|
# something beyond a simple insert (eg. Oracle).
|
352
|
+
# Most of adapters should implement `insert_fixtures_set` that leverages bulk SQL insert.
|
353
|
+
# We keep this method to provide fallback
|
354
|
+
# for databases like sqlite that do not support bulk inserts.
|
268
355
|
def insert_fixture(fixture, table_name)
|
269
|
-
|
270
|
-
|
271
|
-
key_list = []
|
272
|
-
value_list = fixture.map do |name, value|
|
273
|
-
key_list << quote_column_name(name)
|
274
|
-
quote(value, columns[name])
|
275
|
-
end
|
276
|
-
|
277
|
-
execute "INSERT INTO #{quote_table_name(table_name)} (#{key_list.join(', ')}) VALUES (#{value_list.join(', ')})", 'Fixture Insert'
|
356
|
+
execute(build_fixture_sql(Array.wrap(fixture), table_name), "Fixture Insert")
|
278
357
|
end
|
279
358
|
|
280
|
-
def
|
281
|
-
|
282
|
-
|
359
|
+
def insert_fixtures_set(fixture_set, tables_to_delete = [])
|
360
|
+
fixture_inserts = build_fixture_statements(fixture_set)
|
361
|
+
table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name(table)}" }
|
362
|
+
total_sql = Array(combine_multi_statements(table_deletes + fixture_inserts))
|
283
363
|
|
284
|
-
|
285
|
-
|
364
|
+
with_multi_statements do
|
365
|
+
disable_referential_integrity do
|
366
|
+
transaction(requires_new: true) do
|
367
|
+
total_sql.each do |sql|
|
368
|
+
execute_batch(sql, "Fixtures Load")
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
372
|
+
end
|
286
373
|
end
|
287
374
|
|
288
|
-
def
|
289
|
-
"
|
375
|
+
def empty_insert_statement_value(primary_key = nil)
|
376
|
+
"DEFAULT VALUES"
|
290
377
|
end
|
291
378
|
|
292
379
|
# Sanitizes the given LIMIT parameter in order to prevent SQL injection.
|
293
380
|
#
|
294
381
|
# The +limit+ may be anything that can evaluate to a string via #to_s. It
|
295
|
-
# should look like an integer, or
|
296
|
-
# an Arel SQL literal.
|
382
|
+
# should look like an integer, or an Arel SQL literal.
|
297
383
|
#
|
298
384
|
# Returns Integer and Arel::Nodes::SqlLiteral limits as is.
|
299
|
-
# Returns the sanitized limit parameter, either as an integer, or as a
|
300
|
-
# string which contains a comma-delimited list of integers.
|
301
385
|
def sanitize_limit(limit)
|
302
386
|
if limit.is_a?(Integer) || limit.is_a?(Arel::Nodes::SqlLiteral)
|
303
387
|
limit
|
304
|
-
elsif limit.to_s =~ /,/
|
305
|
-
Arel.sql limit.to_s.split(',').map{ |i| Integer(i) }.join(',')
|
306
388
|
else
|
307
389
|
Integer(limit)
|
308
390
|
end
|
309
391
|
end
|
310
392
|
|
311
|
-
#
|
312
|
-
#
|
313
|
-
#
|
314
|
-
def
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
end
|
320
|
-
|
321
|
-
protected
|
322
|
-
# Returns an array of record hashes with the column names as keys and
|
323
|
-
# column values as values.
|
324
|
-
def select(sql, name = nil, binds = [])
|
393
|
+
# Fixture value is quoted by Arel, however scalar values
|
394
|
+
# are not quotable. In this case we want to convert
|
395
|
+
# the column value to YAML.
|
396
|
+
def with_yaml_fallback(value) # :nodoc:
|
397
|
+
if value.is_a?(Hash) || value.is_a?(Array)
|
398
|
+
YAML.dump(value)
|
399
|
+
else
|
400
|
+
value
|
325
401
|
end
|
326
|
-
|
402
|
+
end
|
327
403
|
|
328
|
-
|
329
|
-
def
|
404
|
+
private
|
405
|
+
def execute_batch(sql, name = nil)
|
330
406
|
execute(sql, name)
|
331
|
-
id_value
|
332
407
|
end
|
333
408
|
|
334
|
-
|
335
|
-
|
336
|
-
execute(sql, name)
|
337
|
-
end
|
409
|
+
DEFAULT_INSERT_VALUE = Arel.sql("DEFAULT").freeze
|
410
|
+
private_constant :DEFAULT_INSERT_VALUE
|
338
411
|
|
339
|
-
|
340
|
-
|
341
|
-
update_sql(sql, name)
|
412
|
+
def default_insert_value(column)
|
413
|
+
DEFAULT_INSERT_VALUE
|
342
414
|
end
|
343
415
|
|
344
|
-
|
345
|
-
|
346
|
-
def rollback_transaction_records(rollback)
|
347
|
-
if rollback
|
348
|
-
records = @_current_transaction_records.flatten
|
349
|
-
@_current_transaction_records.clear
|
350
|
-
else
|
351
|
-
records = @_current_transaction_records.pop
|
352
|
-
end
|
416
|
+
def build_fixture_sql(fixtures, table_name)
|
417
|
+
columns = schema_cache.columns_hash(table_name)
|
353
418
|
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
419
|
+
values_list = fixtures.map do |fixture|
|
420
|
+
fixture = fixture.stringify_keys
|
421
|
+
|
422
|
+
unknown_columns = fixture.keys - columns.keys
|
423
|
+
if unknown_columns.any?
|
424
|
+
raise Fixture::FixtureError, %(table "#{table_name}" has no columns named #{unknown_columns.map(&:inspect).join(', ')}.)
|
425
|
+
end
|
426
|
+
|
427
|
+
columns.map do |name, column|
|
428
|
+
if fixture.key?(name)
|
429
|
+
type = lookup_cast_type_from_column(column)
|
430
|
+
with_yaml_fallback(type.serialize(fixture[name]))
|
431
|
+
else
|
432
|
+
default_insert_value(column)
|
360
433
|
end
|
361
434
|
end
|
362
435
|
end
|
363
|
-
end
|
364
436
|
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
437
|
+
table = Arel::Table.new(table_name)
|
438
|
+
manager = Arel::InsertManager.new
|
439
|
+
manager.into(table)
|
440
|
+
|
441
|
+
if values_list.size == 1
|
442
|
+
values = values_list.shift
|
443
|
+
new_values = []
|
444
|
+
columns.each_key.with_index { |column, i|
|
445
|
+
unless values[i].equal?(DEFAULT_INSERT_VALUE)
|
446
|
+
new_values << values[i]
|
447
|
+
manager.columns << table[column]
|
375
448
|
end
|
376
|
-
|
449
|
+
}
|
450
|
+
values_list << new_values
|
451
|
+
else
|
452
|
+
columns.each_key { |column| manager.columns << table[column] }
|
377
453
|
end
|
454
|
+
|
455
|
+
manager.values = manager.create_values_list(values_list)
|
456
|
+
manager.to_sql
|
378
457
|
end
|
379
458
|
|
380
|
-
|
381
|
-
|
382
|
-
|
459
|
+
def build_fixture_statements(fixture_set)
|
460
|
+
fixture_set.map do |table_name, fixtures|
|
461
|
+
next if fixtures.empty?
|
462
|
+
build_fixture_sql(fixtures, table_name)
|
463
|
+
end.compact
|
464
|
+
end
|
383
465
|
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
466
|
+
def build_truncate_statements(*table_names)
|
467
|
+
truncate_tables = table_names.map do |table_name|
|
468
|
+
"TRUNCATE TABLE #{quote_table_name(table_name)}"
|
469
|
+
end
|
470
|
+
combine_multi_statements(truncate_tables)
|
471
|
+
end
|
472
|
+
|
473
|
+
def with_multi_statements
|
474
|
+
yield
|
475
|
+
end
|
476
|
+
|
477
|
+
def combine_multi_statements(total_sql)
|
478
|
+
total_sql.join(";\n")
|
479
|
+
end
|
480
|
+
|
481
|
+
# Returns an ActiveRecord::Result instance.
|
482
|
+
def select(sql, name = nil, binds = [])
|
483
|
+
exec_query(sql, name, binds, prepare: false)
|
484
|
+
end
|
485
|
+
|
486
|
+
def select_prepared(sql, name = nil, binds = [])
|
487
|
+
exec_query(sql, name, binds, prepare: true)
|
488
|
+
end
|
489
|
+
|
490
|
+
def sql_for_insert(sql, pk, binds)
|
491
|
+
[sql, binds]
|
492
|
+
end
|
493
|
+
|
494
|
+
def last_inserted_id(result)
|
495
|
+
single_value_from_rows(result.rows)
|
496
|
+
end
|
497
|
+
|
498
|
+
def single_value_from_rows(rows)
|
499
|
+
row = rows.first
|
500
|
+
row && row.first
|
501
|
+
end
|
502
|
+
|
503
|
+
def arel_from_relation(relation)
|
504
|
+
if relation.is_a?(Relation)
|
505
|
+
relation.arel
|
506
|
+
else
|
507
|
+
relation
|
508
|
+
end
|
509
|
+
end
|
388
510
|
end
|
389
511
|
end
|
390
512
|
end
|