activerecord 2.3.18 → 3.2.22
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 +1014 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +222 -0
- data/examples/performance.rb +100 -126
- data/examples/simple.rb +14 -0
- data/lib/active_record/aggregations.rb +93 -99
- data/lib/active_record/associations/alias_tracker.rb +76 -0
- data/lib/active_record/associations/association.rb +247 -0
- data/lib/active_record/associations/association_scope.rb +134 -0
- data/lib/active_record/associations/belongs_to_association.rb +54 -61
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +17 -59
- data/lib/active_record/associations/builder/association.rb +55 -0
- data/lib/active_record/associations/builder/belongs_to.rb +88 -0
- data/lib/active_record/associations/builder/collection_association.rb +75 -0
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +57 -0
- data/lib/active_record/associations/builder/has_many.rb +71 -0
- data/lib/active_record/associations/builder/has_one.rb +62 -0
- data/lib/active_record/associations/builder/singular_association.rb +32 -0
- data/lib/active_record/associations/collection_association.rb +580 -0
- data/lib/active_record/associations/collection_proxy.rb +133 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +39 -119
- data/lib/active_record/associations/has_many_association.rb +60 -79
- data/lib/active_record/associations/has_many_through_association.rb +127 -206
- data/lib/active_record/associations/has_one_association.rb +55 -114
- data/lib/active_record/associations/has_one_through_association.rb +25 -26
- data/lib/active_record/associations/join_dependency/join_association.rb +159 -0
- data/lib/active_record/associations/join_dependency/join_base.rb +24 -0
- data/lib/active_record/associations/join_dependency/join_part.rb +78 -0
- data/lib/active_record/associations/join_dependency.rb +214 -0
- data/lib/active_record/associations/join_helper.rb +55 -0
- data/lib/active_record/associations/preloader/association.rb +125 -0
- data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
- data/lib/active_record/associations/preloader/collection_association.rb +24 -0
- data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +60 -0
- data/lib/active_record/associations/preloader/has_many.rb +17 -0
- data/lib/active_record/associations/preloader/has_many_through.rb +15 -0
- data/lib/active_record/associations/preloader/has_one.rb +23 -0
- data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
- data/lib/active_record/associations/preloader/singular_association.rb +21 -0
- data/lib/active_record/associations/preloader/through_association.rb +67 -0
- data/lib/active_record/associations/preloader.rb +181 -0
- data/lib/active_record/associations/singular_association.rb +64 -0
- data/lib/active_record/associations/through_association.rb +87 -0
- data/lib/active_record/associations.rb +693 -1337
- data/lib/active_record/attribute_assignment.rb +221 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +31 -0
- data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +32 -0
- data/lib/active_record/attribute_methods/dirty.rb +111 -0
- data/lib/active_record/attribute_methods/primary_key.rb +114 -0
- data/lib/active_record/attribute_methods/query.rb +39 -0
- data/lib/active_record/attribute_methods/read.rb +136 -0
- data/lib/active_record/attribute_methods/serialization.rb +120 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +65 -0
- data/lib/active_record/attribute_methods/write.rb +70 -0
- data/lib/active_record/attribute_methods.rb +211 -339
- data/lib/active_record/autosave_association.rb +179 -149
- data/lib/active_record/base.rb +401 -2907
- data/lib/active_record/callbacks.rb +91 -176
- data/lib/active_record/coders/yaml_column.rb +41 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +236 -119
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +110 -58
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +12 -11
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +175 -74
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -35
- data/lib/active_record/connection_adapters/abstract/quoting.rb +71 -21
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +81 -311
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +194 -78
- data/lib/active_record/connection_adapters/abstract_adapter.rb +130 -83
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +676 -0
- data/lib/active_record/connection_adapters/column.rb +296 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +280 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +272 -493
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +650 -405
- data/lib/active_record/connection_adapters/schema_cache.rb +69 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +30 -9
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +276 -147
- data/lib/active_record/connection_adapters/statement_pool.rb +40 -0
- data/lib/active_record/counter_cache.rb +123 -0
- data/lib/active_record/dynamic_finder_match.rb +41 -14
- data/lib/active_record/dynamic_matchers.rb +84 -0
- data/lib/active_record/dynamic_scope_match.rb +13 -15
- data/lib/active_record/errors.rb +195 -0
- data/lib/active_record/explain.rb +86 -0
- data/lib/active_record/explain_subscriber.rb +25 -0
- data/lib/active_record/fixtures/file.rb +65 -0
- data/lib/active_record/fixtures.rb +695 -770
- data/lib/active_record/identity_map.rb +162 -0
- data/lib/active_record/inheritance.rb +174 -0
- data/lib/active_record/integration.rb +60 -0
- data/lib/active_record/locale/en.yml +9 -27
- data/lib/active_record/locking/optimistic.rb +76 -73
- data/lib/active_record/locking/pessimistic.rb +32 -10
- data/lib/active_record/log_subscriber.rb +72 -0
- data/lib/active_record/migration/command_recorder.rb +105 -0
- data/lib/active_record/migration.rb +415 -205
- data/lib/active_record/model_schema.rb +368 -0
- data/lib/active_record/nested_attributes.rb +153 -63
- data/lib/active_record/observer.rb +27 -103
- data/lib/active_record/persistence.rb +376 -0
- data/lib/active_record/query_cache.rb +49 -8
- data/lib/active_record/querying.rb +58 -0
- data/lib/active_record/railtie.rb +131 -0
- data/lib/active_record/railties/console_sandbox.rb +6 -0
- data/lib/active_record/railties/controller_runtime.rb +49 -0
- data/lib/active_record/railties/databases.rake +659 -0
- data/lib/active_record/railties/jdbcmysql_error.rb +16 -0
- data/lib/active_record/readonly_attributes.rb +26 -0
- data/lib/active_record/reflection.rb +269 -120
- data/lib/active_record/relation/batches.rb +90 -0
- data/lib/active_record/relation/calculations.rb +372 -0
- data/lib/active_record/relation/delegation.rb +49 -0
- data/lib/active_record/relation/finder_methods.rb +402 -0
- data/lib/active_record/relation/predicate_builder.rb +63 -0
- data/lib/active_record/relation/query_methods.rb +417 -0
- data/lib/active_record/relation/spawn_methods.rb +180 -0
- data/lib/active_record/relation.rb +537 -0
- data/lib/active_record/result.rb +40 -0
- data/lib/active_record/sanitization.rb +194 -0
- data/lib/active_record/schema.rb +9 -6
- data/lib/active_record/schema_dumper.rb +55 -32
- data/lib/active_record/scoping/default.rb +142 -0
- data/lib/active_record/scoping/named.rb +200 -0
- data/lib/active_record/scoping.rb +152 -0
- data/lib/active_record/serialization.rb +8 -91
- data/lib/active_record/serializers/xml_serializer.rb +43 -197
- data/lib/active_record/session_store.rb +129 -103
- data/lib/active_record/store.rb +52 -0
- data/lib/active_record/test_case.rb +30 -23
- data/lib/active_record/timestamp.rb +95 -52
- data/lib/active_record/transactions.rb +212 -66
- data/lib/active_record/translation.rb +22 -0
- data/lib/active_record/validations/associated.rb +43 -0
- data/lib/active_record/validations/uniqueness.rb +180 -0
- data/lib/active_record/validations.rb +43 -1106
- data/lib/active_record/version.rb +5 -4
- data/lib/active_record.rb +121 -48
- data/lib/rails/generators/active_record/migration/migration_generator.rb +25 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb +34 -0
- data/lib/rails/generators/active_record/migration.rb +15 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +47 -0
- data/lib/rails/generators/active_record/model/templates/migration.rb +15 -0
- data/lib/rails/generators/active_record/model/templates/model.rb +12 -0
- data/lib/rails/generators/active_record/model/templates/module.rb +7 -0
- data/lib/rails/generators/active_record/observer/observer_generator.rb +15 -0
- data/lib/rails/generators/active_record/observer/templates/observer.rb +4 -0
- data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +25 -0
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +12 -0
- data/lib/rails/generators/active_record.rb +25 -0
- metadata +187 -363
- data/CHANGELOG +0 -5904
- data/README +0 -351
- data/RUNNING_UNIT_TESTS +0 -36
- data/Rakefile +0 -268
- data/install.rb +0 -30
- data/lib/active_record/association_preload.rb +0 -406
- data/lib/active_record/associations/association_collection.rb +0 -533
- data/lib/active_record/associations/association_proxy.rb +0 -288
- data/lib/active_record/batches.rb +0 -85
- data/lib/active_record/calculations.rb +0 -321
- data/lib/active_record/dirty.rb +0 -183
- data/lib/active_record/named_scope.rb +0 -197
- data/lib/active_record/serializers/json_serializer.rb +0 -91
- data/lib/activerecord.rb +0 -2
- data/test/assets/example.log +0 -1
- data/test/assets/flowers.jpg +0 -0
- data/test/cases/aaa_create_tables_test.rb +0 -24
- data/test/cases/active_schema_test_mysql.rb +0 -122
- data/test/cases/active_schema_test_postgresql.rb +0 -24
- data/test/cases/adapter_test.rb +0 -144
- data/test/cases/aggregations_test.rb +0 -167
- data/test/cases/ar_schema_test.rb +0 -32
- data/test/cases/associations/belongs_to_associations_test.rb +0 -438
- data/test/cases/associations/callbacks_test.rb +0 -161
- data/test/cases/associations/cascaded_eager_loading_test.rb +0 -131
- data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +0 -36
- data/test/cases/associations/eager_load_nested_include_test.rb +0 -131
- data/test/cases/associations/eager_load_nested_polymorphic_include.rb +0 -19
- data/test/cases/associations/eager_singularization_test.rb +0 -145
- data/test/cases/associations/eager_test.rb +0 -852
- data/test/cases/associations/extension_test.rb +0 -62
- data/test/cases/associations/habtm_join_table_test.rb +0 -56
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +0 -827
- data/test/cases/associations/has_many_associations_test.rb +0 -1273
- data/test/cases/associations/has_many_through_associations_test.rb +0 -360
- data/test/cases/associations/has_one_associations_test.rb +0 -330
- data/test/cases/associations/has_one_through_associations_test.rb +0 -209
- data/test/cases/associations/inner_join_association_test.rb +0 -93
- data/test/cases/associations/inverse_associations_test.rb +0 -566
- data/test/cases/associations/join_model_test.rb +0 -712
- data/test/cases/associations_test.rb +0 -282
- data/test/cases/attribute_methods_test.rb +0 -305
- data/test/cases/autosave_association_test.rb +0 -1218
- data/test/cases/base_test.rb +0 -2166
- data/test/cases/batches_test.rb +0 -81
- data/test/cases/binary_test.rb +0 -30
- data/test/cases/calculations_test.rb +0 -360
- data/test/cases/callbacks_observers_test.rb +0 -38
- data/test/cases/callbacks_test.rb +0 -438
- data/test/cases/class_inheritable_attributes_test.rb +0 -32
- data/test/cases/column_alias_test.rb +0 -17
- data/test/cases/column_definition_test.rb +0 -70
- data/test/cases/connection_pool_test.rb +0 -25
- data/test/cases/connection_test_firebird.rb +0 -8
- data/test/cases/connection_test_mysql.rb +0 -65
- data/test/cases/copy_table_test_sqlite.rb +0 -80
- data/test/cases/counter_cache_test.rb +0 -84
- data/test/cases/database_statements_test.rb +0 -12
- data/test/cases/datatype_test_postgresql.rb +0 -204
- data/test/cases/date_time_test.rb +0 -37
- data/test/cases/default_test_firebird.rb +0 -16
- data/test/cases/defaults_test.rb +0 -111
- data/test/cases/deprecated_finder_test.rb +0 -30
- data/test/cases/dirty_test.rb +0 -316
- data/test/cases/finder_respond_to_test.rb +0 -76
- data/test/cases/finder_test.rb +0 -1098
- data/test/cases/fixtures_test.rb +0 -661
- data/test/cases/helper.rb +0 -68
- data/test/cases/i18n_test.rb +0 -46
- data/test/cases/inheritance_test.rb +0 -262
- data/test/cases/invalid_date_test.rb +0 -24
- data/test/cases/json_serialization_test.rb +0 -219
- data/test/cases/lifecycle_test.rb +0 -193
- data/test/cases/locking_test.rb +0 -350
- data/test/cases/method_scoping_test.rb +0 -704
- data/test/cases/migration_test.rb +0 -1649
- data/test/cases/migration_test_firebird.rb +0 -124
- data/test/cases/mixin_test.rb +0 -96
- data/test/cases/modules_test.rb +0 -109
- data/test/cases/multiple_db_test.rb +0 -85
- data/test/cases/named_scope_test.rb +0 -372
- data/test/cases/nested_attributes_test.rb +0 -840
- data/test/cases/pk_test.rb +0 -119
- data/test/cases/pooled_connections_test.rb +0 -103
- data/test/cases/query_cache_test.rb +0 -129
- data/test/cases/readonly_test.rb +0 -107
- data/test/cases/reflection_test.rb +0 -234
- data/test/cases/reload_models_test.rb +0 -22
- data/test/cases/repair_helper.rb +0 -50
- data/test/cases/reserved_word_test_mysql.rb +0 -176
- data/test/cases/sanitize_test.rb +0 -25
- data/test/cases/schema_authorization_test_postgresql.rb +0 -75
- data/test/cases/schema_dumper_test.rb +0 -211
- data/test/cases/schema_test_postgresql.rb +0 -178
- data/test/cases/serialization_test.rb +0 -47
- data/test/cases/sp_test_mysql.rb +0 -16
- data/test/cases/synonym_test_oracle.rb +0 -17
- data/test/cases/timestamp_test.rb +0 -75
- data/test/cases/transactions_test.rb +0 -543
- data/test/cases/unconnected_test.rb +0 -32
- data/test/cases/validations_i18n_test.rb +0 -925
- data/test/cases/validations_test.rb +0 -1684
- data/test/cases/xml_serialization_test.rb +0 -240
- data/test/cases/yaml_serialization_test.rb +0 -11
- data/test/config.rb +0 -5
- data/test/connections/jdbc_jdbcderby/connection.rb +0 -18
- data/test/connections/jdbc_jdbch2/connection.rb +0 -18
- data/test/connections/jdbc_jdbchsqldb/connection.rb +0 -18
- data/test/connections/jdbc_jdbcmysql/connection.rb +0 -26
- data/test/connections/jdbc_jdbcpostgresql/connection.rb +0 -26
- data/test/connections/jdbc_jdbcsqlite3/connection.rb +0 -25
- data/test/connections/native_db2/connection.rb +0 -25
- data/test/connections/native_firebird/connection.rb +0 -26
- data/test/connections/native_frontbase/connection.rb +0 -27
- data/test/connections/native_mysql/connection.rb +0 -25
- data/test/connections/native_openbase/connection.rb +0 -21
- data/test/connections/native_oracle/connection.rb +0 -27
- data/test/connections/native_postgresql/connection.rb +0 -21
- data/test/connections/native_sqlite/connection.rb +0 -25
- data/test/connections/native_sqlite3/connection.rb +0 -25
- data/test/connections/native_sqlite3/in_memory_connection.rb +0 -18
- data/test/connections/native_sybase/connection.rb +0 -23
- data/test/fixtures/accounts.yml +0 -29
- data/test/fixtures/all/developers.yml +0 -0
- data/test/fixtures/all/people.csv +0 -0
- data/test/fixtures/all/tasks.yml +0 -0
- data/test/fixtures/author_addresses.yml +0 -5
- data/test/fixtures/author_favorites.yml +0 -4
- data/test/fixtures/authors.yml +0 -9
- data/test/fixtures/binaries.yml +0 -132
- data/test/fixtures/books.yml +0 -7
- data/test/fixtures/categories/special_categories.yml +0 -9
- data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +0 -4
- data/test/fixtures/categories.yml +0 -14
- data/test/fixtures/categories_ordered.yml +0 -7
- data/test/fixtures/categories_posts.yml +0 -23
- data/test/fixtures/categorizations.yml +0 -17
- data/test/fixtures/clubs.yml +0 -6
- data/test/fixtures/comments.yml +0 -59
- data/test/fixtures/companies.yml +0 -56
- data/test/fixtures/computers.yml +0 -4
- data/test/fixtures/courses.yml +0 -7
- data/test/fixtures/customers.yml +0 -26
- data/test/fixtures/developers.yml +0 -21
- data/test/fixtures/developers_projects.yml +0 -17
- data/test/fixtures/edges.yml +0 -6
- data/test/fixtures/entrants.yml +0 -14
- data/test/fixtures/faces.yml +0 -11
- data/test/fixtures/fk_test_has_fk.yml +0 -3
- data/test/fixtures/fk_test_has_pk.yml +0 -2
- data/test/fixtures/funny_jokes.yml +0 -10
- data/test/fixtures/interests.yml +0 -33
- data/test/fixtures/items.yml +0 -4
- data/test/fixtures/jobs.yml +0 -7
- data/test/fixtures/legacy_things.yml +0 -3
- data/test/fixtures/mateys.yml +0 -4
- data/test/fixtures/member_types.yml +0 -6
- data/test/fixtures/members.yml +0 -6
- data/test/fixtures/memberships.yml +0 -20
- data/test/fixtures/men.yml +0 -5
- data/test/fixtures/minimalistics.yml +0 -2
- data/test/fixtures/mixed_case_monkeys.yml +0 -6
- data/test/fixtures/mixins.yml +0 -29
- data/test/fixtures/movies.yml +0 -7
- data/test/fixtures/naked/csv/accounts.csv +0 -1
- data/test/fixtures/naked/yml/accounts.yml +0 -1
- data/test/fixtures/naked/yml/companies.yml +0 -1
- data/test/fixtures/naked/yml/courses.yml +0 -1
- data/test/fixtures/organizations.yml +0 -5
- data/test/fixtures/owners.yml +0 -7
- data/test/fixtures/parrots.yml +0 -27
- data/test/fixtures/parrots_pirates.yml +0 -7
- data/test/fixtures/people.yml +0 -15
- data/test/fixtures/pets.yml +0 -14
- data/test/fixtures/pirates.yml +0 -9
- data/test/fixtures/polymorphic_designs.yml +0 -19
- data/test/fixtures/polymorphic_prices.yml +0 -19
- data/test/fixtures/posts.yml +0 -52
- data/test/fixtures/price_estimates.yml +0 -7
- data/test/fixtures/projects.yml +0 -7
- data/test/fixtures/readers.yml +0 -9
- data/test/fixtures/references.yml +0 -17
- data/test/fixtures/reserved_words/distinct.yml +0 -5
- data/test/fixtures/reserved_words/distincts_selects.yml +0 -11
- data/test/fixtures/reserved_words/group.yml +0 -14
- data/test/fixtures/reserved_words/select.yml +0 -8
- data/test/fixtures/reserved_words/values.yml +0 -7
- data/test/fixtures/ships.yml +0 -5
- data/test/fixtures/sponsors.yml +0 -9
- data/test/fixtures/subscribers.yml +0 -7
- data/test/fixtures/subscriptions.yml +0 -12
- data/test/fixtures/taggings.yml +0 -28
- data/test/fixtures/tags.yml +0 -7
- data/test/fixtures/tasks.yml +0 -7
- data/test/fixtures/tees.yml +0 -4
- data/test/fixtures/ties.yml +0 -4
- data/test/fixtures/topics.yml +0 -42
- data/test/fixtures/toys.yml +0 -4
- data/test/fixtures/treasures.yml +0 -10
- data/test/fixtures/vertices.yml +0 -4
- data/test/fixtures/warehouse-things.yml +0 -3
- data/test/fixtures/zines.yml +0 -5
- data/test/migrations/broken/100_migration_that_raises_exception.rb +0 -10
- data/test/migrations/decimal/1_give_me_big_numbers.rb +0 -15
- data/test/migrations/duplicate/1_people_have_last_names.rb +0 -9
- data/test/migrations/duplicate/2_we_need_reminders.rb +0 -12
- data/test/migrations/duplicate/3_foo.rb +0 -7
- data/test/migrations/duplicate/3_innocent_jointable.rb +0 -12
- data/test/migrations/duplicate_names/20080507052938_chunky.rb +0 -7
- data/test/migrations/duplicate_names/20080507053028_chunky.rb +0 -7
- data/test/migrations/interleaved/pass_1/3_innocent_jointable.rb +0 -12
- data/test/migrations/interleaved/pass_2/1_people_have_last_names.rb +0 -9
- data/test/migrations/interleaved/pass_2/3_innocent_jointable.rb +0 -12
- data/test/migrations/interleaved/pass_3/1_people_have_last_names.rb +0 -9
- data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +0 -8
- data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +0 -12
- data/test/migrations/missing/1000_people_have_middle_names.rb +0 -9
- data/test/migrations/missing/1_people_have_last_names.rb +0 -9
- data/test/migrations/missing/3_we_need_reminders.rb +0 -12
- data/test/migrations/missing/4_innocent_jointable.rb +0 -12
- data/test/migrations/valid/1_people_have_last_names.rb +0 -9
- data/test/migrations/valid/2_we_need_reminders.rb +0 -12
- data/test/migrations/valid/3_innocent_jointable.rb +0 -12
- data/test/models/author.rb +0 -151
- data/test/models/auto_id.rb +0 -4
- data/test/models/binary.rb +0 -2
- data/test/models/bird.rb +0 -9
- data/test/models/book.rb +0 -4
- data/test/models/categorization.rb +0 -5
- data/test/models/category.rb +0 -34
- data/test/models/citation.rb +0 -6
- data/test/models/club.rb +0 -13
- data/test/models/column_name.rb +0 -3
- data/test/models/comment.rb +0 -29
- data/test/models/company.rb +0 -173
- data/test/models/company_in_module.rb +0 -78
- data/test/models/computer.rb +0 -3
- data/test/models/contact.rb +0 -16
- data/test/models/contract.rb +0 -5
- data/test/models/course.rb +0 -3
- data/test/models/customer.rb +0 -73
- data/test/models/default.rb +0 -2
- data/test/models/developer.rb +0 -101
- data/test/models/edge.rb +0 -5
- data/test/models/entrant.rb +0 -3
- data/test/models/essay.rb +0 -3
- data/test/models/event.rb +0 -3
- data/test/models/event_author.rb +0 -8
- data/test/models/face.rb +0 -7
- data/test/models/guid.rb +0 -2
- data/test/models/interest.rb +0 -5
- data/test/models/invoice.rb +0 -4
- data/test/models/item.rb +0 -7
- data/test/models/job.rb +0 -5
- data/test/models/joke.rb +0 -3
- data/test/models/keyboard.rb +0 -3
- data/test/models/legacy_thing.rb +0 -3
- data/test/models/line_item.rb +0 -3
- data/test/models/man.rb +0 -9
- data/test/models/matey.rb +0 -4
- data/test/models/member.rb +0 -12
- data/test/models/member_detail.rb +0 -5
- data/test/models/member_type.rb +0 -3
- data/test/models/membership.rb +0 -9
- data/test/models/minimalistic.rb +0 -2
- data/test/models/mixed_case_monkey.rb +0 -3
- data/test/models/movie.rb +0 -5
- data/test/models/order.rb +0 -4
- data/test/models/organization.rb +0 -6
- data/test/models/owner.rb +0 -5
- data/test/models/parrot.rb +0 -22
- data/test/models/person.rb +0 -16
- data/test/models/pet.rb +0 -5
- data/test/models/pirate.rb +0 -80
- data/test/models/polymorphic_design.rb +0 -3
- data/test/models/polymorphic_price.rb +0 -3
- data/test/models/post.rb +0 -102
- data/test/models/price_estimate.rb +0 -3
- data/test/models/project.rb +0 -30
- data/test/models/reader.rb +0 -4
- data/test/models/reference.rb +0 -4
- data/test/models/reply.rb +0 -46
- data/test/models/ship.rb +0 -19
- data/test/models/ship_part.rb +0 -7
- data/test/models/sponsor.rb +0 -4
- data/test/models/subject.rb +0 -4
- data/test/models/subscriber.rb +0 -8
- data/test/models/subscription.rb +0 -4
- data/test/models/tag.rb +0 -7
- data/test/models/tagging.rb +0 -10
- data/test/models/task.rb +0 -3
- data/test/models/tee.rb +0 -4
- data/test/models/tie.rb +0 -4
- data/test/models/topic.rb +0 -80
- data/test/models/toy.rb +0 -6
- data/test/models/treasure.rb +0 -8
- data/test/models/vertex.rb +0 -9
- data/test/models/warehouse_thing.rb +0 -5
- data/test/models/zine.rb +0 -3
- data/test/schema/mysql_specific_schema.rb +0 -31
- data/test/schema/postgresql_specific_schema.rb +0 -114
- data/test/schema/schema.rb +0 -550
- data/test/schema/schema2.rb +0 -6
- data/test/schema/sqlite_specific_schema.rb +0 -25
@@ -1,5 +1,7 @@
|
|
1
|
+
require 'thread'
|
1
2
|
require 'monitor'
|
2
3
|
require 'set'
|
4
|
+
require 'active_support/core_ext/module/deprecation'
|
3
5
|
|
4
6
|
module ActiveRecord
|
5
7
|
# Raised when a connection could not be obtained within the connection
|
@@ -8,7 +10,7 @@ module ActiveRecord
|
|
8
10
|
end
|
9
11
|
|
10
12
|
module ConnectionAdapters
|
11
|
-
# Connection pool base class for managing
|
13
|
+
# Connection pool base class for managing Active Record database
|
12
14
|
# connections.
|
13
15
|
#
|
14
16
|
# == Introduction
|
@@ -29,12 +31,12 @@ module ActiveRecord
|
|
29
31
|
# Connections can be obtained and used from a connection pool in several
|
30
32
|
# ways:
|
31
33
|
#
|
32
|
-
# 1. Simply use ActiveRecord::Base.connection as with
|
34
|
+
# 1. Simply use ActiveRecord::Base.connection as with Active Record 2.1 and
|
33
35
|
# earlier (pre-connection-pooling). Eventually, when you're done with
|
34
36
|
# the connection(s) and wish it to be returned to the pool, you call
|
35
37
|
# ActiveRecord::Base.clear_active_connections!. This will be the
|
36
|
-
# default behavior for
|
37
|
-
#
|
38
|
+
# default behavior for Active Record when used in conjunction with
|
39
|
+
# Action Pack's request handling cycle.
|
38
40
|
# 2. Manually check out a connection from the pool with
|
39
41
|
# ActiveRecord::Base.connection_pool.checkout. You are responsible for
|
40
42
|
# returning this connection to the pool when finished by calling
|
@@ -52,10 +54,16 @@ module ActiveRecord
|
|
52
54
|
# your database connection configuration:
|
53
55
|
#
|
54
56
|
# * +pool+: number indicating size of connection pool (default 5)
|
55
|
-
# * +
|
56
|
-
# before giving up and raising a timeout error
|
57
|
+
# * +checkout _timeout+: number of seconds to block and wait for a
|
58
|
+
# connection before giving up and raising a timeout error
|
59
|
+
# (default 5 seconds). ('wait_timeout' supported for backwards
|
60
|
+
# compatibility, but conflicts with key used for different purpose
|
61
|
+
# by mysql2 adapter).
|
57
62
|
class ConnectionPool
|
58
|
-
|
63
|
+
include MonitorMixin
|
64
|
+
|
65
|
+
attr_accessor :automatic_reconnect
|
66
|
+
attr_reader :spec, :connections
|
59
67
|
|
60
68
|
# Creates a new ConnectionPool object. +spec+ is a ConnectionSpecification
|
61
69
|
# object which describes database connection information (e.g. adapter,
|
@@ -64,26 +72,24 @@ module ActiveRecord
|
|
64
72
|
#
|
65
73
|
# The default ConnectionPool maximum size is 5.
|
66
74
|
def initialize(spec)
|
75
|
+
super()
|
76
|
+
|
67
77
|
@spec = spec
|
68
78
|
|
69
79
|
# The cache of reserved connections mapped to threads
|
70
80
|
@reserved_connections = {}
|
71
81
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
@timeout =
|
78
|
-
if RUBY_VERSION < '1.9'
|
79
|
-
spec.config[:wait_timeout] || 5
|
80
|
-
end
|
82
|
+
@queue = new_cond
|
83
|
+
# 'wait_timeout', the backward-compatible key, conflicts with spec key
|
84
|
+
# used by mysql2 for something entirely different, checkout_timeout
|
85
|
+
# preferred to avoid conflict and allow independent values.
|
86
|
+
@timeout = spec.config[:checkout_timeout] || spec.config[:wait_timeout] || 5
|
81
87
|
|
82
88
|
# default max pool size to 5
|
83
89
|
@size = (spec.config[:pool] && spec.config[:pool].to_i) || 5
|
84
90
|
|
85
|
-
@connections
|
86
|
-
@
|
91
|
+
@connections = []
|
92
|
+
@automatic_reconnect = true
|
87
93
|
end
|
88
94
|
|
89
95
|
# Retrieve the connection associated with the current thread, or call
|
@@ -92,73 +98,124 @@ module ActiveRecord
|
|
92
98
|
# #connection can be called any number of times; the connection is
|
93
99
|
# held in a hash keyed by the thread id.
|
94
100
|
def connection
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
101
|
+
synchronize do
|
102
|
+
@reserved_connections[current_connection_id] ||= checkout
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Is there an open connection that is being used for the current thread?
|
107
|
+
def active_connection?
|
108
|
+
synchronize do
|
109
|
+
@reserved_connections.fetch(current_connection_id) {
|
110
|
+
return false
|
111
|
+
}.in_use?
|
99
112
|
end
|
100
113
|
end
|
101
114
|
|
102
115
|
# Signal that the thread is finished with the current connection.
|
103
116
|
# #release_connection releases the connection-thread association
|
104
117
|
# and returns the connection to the pool.
|
105
|
-
def release_connection
|
106
|
-
conn = @reserved_connections.delete(
|
118
|
+
def release_connection(with_id = current_connection_id)
|
119
|
+
conn = synchronize { @reserved_connections.delete(with_id) }
|
107
120
|
checkin conn if conn
|
108
121
|
end
|
109
122
|
|
110
|
-
#
|
111
|
-
#
|
123
|
+
# If a connection already exists yield it to the block. If no connection
|
124
|
+
# exists checkout a connection, yield it to the block, and checkin the
|
125
|
+
# connection when finished.
|
112
126
|
def with_connection
|
113
|
-
|
114
|
-
|
127
|
+
connection_id = current_connection_id
|
128
|
+
fresh_connection = true unless active_connection?
|
129
|
+
yield connection
|
115
130
|
ensure
|
116
|
-
|
131
|
+
release_connection(connection_id) if fresh_connection
|
117
132
|
end
|
118
133
|
|
119
134
|
# Returns true if a connection has already been opened.
|
120
135
|
def connected?
|
121
|
-
|
136
|
+
synchronize { @connections.any? }
|
122
137
|
end
|
123
138
|
|
124
139
|
# Disconnects all connections in the pool, and clears the pool.
|
125
140
|
def disconnect!
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
141
|
+
synchronize do
|
142
|
+
@reserved_connections = {}
|
143
|
+
@connections.each do |conn|
|
144
|
+
checkin conn
|
145
|
+
conn.disconnect!
|
146
|
+
end
|
147
|
+
@connections = []
|
132
148
|
end
|
133
|
-
@connections = []
|
134
149
|
end
|
135
150
|
|
136
|
-
# Clears the cache which maps classes
|
151
|
+
# Clears the cache which maps classes.
|
137
152
|
def clear_reloadable_connections!
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
153
|
+
synchronize do
|
154
|
+
@reserved_connections = {}
|
155
|
+
@connections.each do |conn|
|
156
|
+
checkin conn
|
157
|
+
conn.disconnect! if conn.requires_reloading?
|
158
|
+
end
|
159
|
+
@connections.delete_if do |conn|
|
160
|
+
conn.requires_reloading?
|
161
|
+
end
|
144
162
|
end
|
145
|
-
@connections = []
|
146
163
|
end
|
147
164
|
|
148
165
|
# Verify active connections and remove and disconnect connections
|
149
166
|
# associated with stale threads.
|
150
167
|
def verify_active_connections! #:nodoc:
|
151
|
-
|
152
|
-
|
153
|
-
connection
|
168
|
+
synchronize do
|
169
|
+
clear_stale_cached_connections!
|
170
|
+
@connections.each do |connection|
|
171
|
+
connection.verify!
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def columns
|
177
|
+
with_connection do |c|
|
178
|
+
c.schema_cache.columns
|
179
|
+
end
|
180
|
+
end
|
181
|
+
deprecate :columns
|
182
|
+
|
183
|
+
def columns_hash
|
184
|
+
with_connection do |c|
|
185
|
+
c.schema_cache.columns_hash
|
186
|
+
end
|
187
|
+
end
|
188
|
+
deprecate :columns_hash
|
189
|
+
|
190
|
+
def primary_keys
|
191
|
+
with_connection do |c|
|
192
|
+
c.schema_cache.primary_keys
|
154
193
|
end
|
155
194
|
end
|
195
|
+
deprecate :primary_keys
|
196
|
+
|
197
|
+
def clear_cache!
|
198
|
+
with_connection do |c|
|
199
|
+
c.schema_cache.clear!
|
200
|
+
end
|
201
|
+
end
|
202
|
+
deprecate :clear_cache!
|
156
203
|
|
157
204
|
# Return any checked-out connections back to the pool by threads that
|
158
205
|
# are no longer alive.
|
159
206
|
def clear_stale_cached_connections!
|
160
|
-
|
207
|
+
keys = @reserved_connections.keys - Thread.list.find_all { |t|
|
208
|
+
t.alive?
|
209
|
+
}.map { |thread| thread.object_id }
|
210
|
+
keys.each do |key|
|
211
|
+
conn = @reserved_connections[key]
|
212
|
+
ActiveSupport::Deprecation.warn(<<-eowarn) if conn.in_use?
|
213
|
+
Database connections will not be closed automatically, please close your
|
214
|
+
database connection at the end of the thread by calling `close` on your
|
215
|
+
connection. For example: ActiveRecord::Base.connection.close
|
216
|
+
eowarn
|
161
217
|
checkin conn
|
218
|
+
@reserved_connections.delete(key)
|
162
219
|
end
|
163
220
|
end
|
164
221
|
|
@@ -179,25 +236,43 @@ module ActiveRecord
|
|
179
236
|
# - ConnectionTimeoutError: no connection can be obtained from the pool
|
180
237
|
# within the timeout period.
|
181
238
|
def checkout
|
182
|
-
|
183
|
-
|
239
|
+
synchronize do
|
240
|
+
waited_time = 0
|
241
|
+
|
184
242
|
loop do
|
185
|
-
conn =
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
# No connections available; wait for one
|
192
|
-
if @queue.wait(@timeout)
|
193
|
-
next
|
194
|
-
else
|
195
|
-
# try looting dead threads
|
196
|
-
clear_stale_cached_connections!
|
197
|
-
if @size == @checked_out.size
|
198
|
-
raise ConnectionTimeoutError, "could not obtain a database connection#{" within #{@timeout} seconds" if @timeout}. The max pool size is currently #{@size}; consider increasing it."
|
243
|
+
conn = @connections.find { |c| c.lease }
|
244
|
+
|
245
|
+
unless conn
|
246
|
+
if @connections.size < @size
|
247
|
+
conn = checkout_new_connection
|
248
|
+
conn.lease
|
199
249
|
end
|
200
250
|
end
|
251
|
+
|
252
|
+
if conn
|
253
|
+
checkout_and_verify conn
|
254
|
+
return conn
|
255
|
+
end
|
256
|
+
|
257
|
+
if waited_time >= @timeout
|
258
|
+
raise ConnectionTimeoutError, "could not obtain a database connection#{" within #{@timeout} seconds" if @timeout} (waited #{waited_time} seconds). The max pool size is currently #{@size}; consider increasing it."
|
259
|
+
end
|
260
|
+
|
261
|
+
# Sometimes our wait can end because a connection is available,
|
262
|
+
# but another thread can snatch it up first. If timeout hasn't
|
263
|
+
# passed but no connection is avail, looks like that happened --
|
264
|
+
# loop and wait again, for the time remaining on our timeout.
|
265
|
+
before_wait = Time.now
|
266
|
+
@queue.wait( [@timeout - waited_time, 0].max )
|
267
|
+
waited_time += (Time.now - before_wait)
|
268
|
+
|
269
|
+
# Will go away in Rails 4, when we don't clean up
|
270
|
+
# after leaked connections automatically anymore. Right now, clean
|
271
|
+
# up after we've returned from a 'wait' if it looks like it's
|
272
|
+
# needed, then loop and try again.
|
273
|
+
if(active_connections.size >= @connections.size)
|
274
|
+
clear_stale_cached_connections!
|
275
|
+
end
|
201
276
|
end
|
202
277
|
end
|
203
278
|
end
|
@@ -208,60 +283,65 @@ module ActiveRecord
|
|
208
283
|
# +conn+: an AbstractAdapter object, which was obtained by earlier by
|
209
284
|
# calling +checkout+ on this pool.
|
210
285
|
def checkin(conn)
|
211
|
-
|
212
|
-
conn.run_callbacks :checkin
|
213
|
-
|
214
|
-
|
286
|
+
synchronize do
|
287
|
+
conn.run_callbacks :checkin do
|
288
|
+
conn.expire
|
289
|
+
@queue.signal
|
290
|
+
end
|
291
|
+
|
292
|
+
release conn
|
215
293
|
end
|
216
294
|
end
|
217
295
|
|
218
|
-
synchronize :clear_reloadable_connections!, :verify_active_connections!,
|
219
|
-
:connected?, :disconnect!, :with => :@connection_mutex
|
220
|
-
|
221
296
|
private
|
297
|
+
|
298
|
+
def release(conn)
|
299
|
+
synchronize do
|
300
|
+
thread_id = nil
|
301
|
+
|
302
|
+
if @reserved_connections[current_connection_id] == conn
|
303
|
+
thread_id = current_connection_id
|
304
|
+
else
|
305
|
+
thread_id = @reserved_connections.keys.find { |k|
|
306
|
+
@reserved_connections[k] == conn
|
307
|
+
}
|
308
|
+
end
|
309
|
+
|
310
|
+
@reserved_connections.delete thread_id if thread_id
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
222
314
|
def new_connection
|
223
315
|
ActiveRecord::Base.send(spec.adapter_method, spec.config)
|
224
316
|
end
|
225
317
|
|
226
318
|
def current_connection_id #:nodoc:
|
227
|
-
Thread.current.object_id
|
228
|
-
end
|
229
|
-
|
230
|
-
# Remove stale threads from the cache.
|
231
|
-
def remove_stale_cached_threads!(cache, &block)
|
232
|
-
keys = Set.new(cache.keys)
|
233
|
-
|
234
|
-
Thread.list.each do |thread|
|
235
|
-
keys.delete(thread.object_id) if thread.alive?
|
236
|
-
end
|
237
|
-
keys.each do |key|
|
238
|
-
next unless cache.has_key?(key)
|
239
|
-
block.call(key, cache[key])
|
240
|
-
cache.delete(key)
|
241
|
-
end
|
319
|
+
ActiveRecord::Base.connection_id ||= Thread.current.object_id
|
242
320
|
end
|
243
321
|
|
244
322
|
def checkout_new_connection
|
323
|
+
raise ConnectionNotEstablished unless @automatic_reconnect
|
324
|
+
|
245
325
|
c = new_connection
|
326
|
+
c.pool = self
|
246
327
|
@connections << c
|
247
|
-
|
248
|
-
end
|
249
|
-
|
250
|
-
def checkout_existing_connection
|
251
|
-
c = (@connections - @checked_out).first
|
252
|
-
checkout_and_verify(c)
|
328
|
+
c
|
253
329
|
end
|
254
330
|
|
255
331
|
def checkout_and_verify(c)
|
256
|
-
c.
|
257
|
-
|
258
|
-
|
332
|
+
c.run_callbacks :checkout do
|
333
|
+
c.verify!
|
334
|
+
end
|
259
335
|
c
|
260
336
|
end
|
337
|
+
|
338
|
+
def active_connections
|
339
|
+
@connections.find_all { |c| c.in_use? }
|
340
|
+
end
|
261
341
|
end
|
262
342
|
|
263
343
|
# ConnectionHandler is a collection of ConnectionPool objects. It is used
|
264
|
-
# for keeping separate connection pools for
|
344
|
+
# for keeping separate connection pools for Active Record models that connect
|
265
345
|
# to different databases.
|
266
346
|
#
|
267
347
|
# For example, suppose that you have 5 models, with the following hierarchy:
|
@@ -281,29 +361,33 @@ module ActiveRecord
|
|
281
361
|
# is not the same as the one used by Book/ScaryBook/GoodBook.
|
282
362
|
#
|
283
363
|
# Normally there is only a single ConnectionHandler instance, accessible via
|
284
|
-
# ActiveRecord::Base.connection_handler.
|
364
|
+
# ActiveRecord::Base.connection_handler. Active Record models use this to
|
285
365
|
# determine that connection pool that they should use.
|
286
366
|
class ConnectionHandler
|
367
|
+
attr_reader :connection_pools
|
368
|
+
|
287
369
|
def initialize(pools = {})
|
288
370
|
@connection_pools = pools
|
371
|
+
@class_to_pool = {}
|
289
372
|
end
|
290
373
|
|
291
|
-
def
|
292
|
-
@connection_pools ||=
|
374
|
+
def establish_connection(name, spec)
|
375
|
+
@connection_pools[spec] ||= ConnectionAdapters::ConnectionPool.new(spec)
|
376
|
+
@class_to_pool[name] = @connection_pools[spec]
|
293
377
|
end
|
294
378
|
|
295
|
-
|
296
|
-
|
379
|
+
# Returns true if there are any active connections among the connection
|
380
|
+
# pools that the ConnectionHandler is managing.
|
381
|
+
def active_connections?
|
382
|
+
connection_pools.values.any? { |pool| pool.active_connection? }
|
297
383
|
end
|
298
384
|
|
299
|
-
# Returns any connections in use by the current thread back to the pool
|
300
|
-
# and also returns connections to the pool cached by threads that are no
|
301
|
-
# longer alive.
|
385
|
+
# Returns any connections in use by the current thread back to the pool.
|
302
386
|
def clear_active_connections!
|
303
387
|
@connection_pools.each_value {|pool| pool.release_connection }
|
304
388
|
end
|
305
389
|
|
306
|
-
# Clears the cache which maps classes
|
390
|
+
# Clears the cache which maps classes.
|
307
391
|
def clear_reloadable_connections!
|
308
392
|
@connection_pools.each_value {|pool| pool.clear_reloadable_connections! }
|
309
393
|
end
|
@@ -330,7 +414,7 @@ module ActiveRecord
|
|
330
414
|
# already been opened.
|
331
415
|
def connected?(klass)
|
332
416
|
conn = retrieve_connection_pool(klass)
|
333
|
-
conn
|
417
|
+
conn && conn.connected?
|
334
418
|
end
|
335
419
|
|
336
420
|
# Remove the connection for this class. This will close the active
|
@@ -338,14 +422,17 @@ module ActiveRecord
|
|
338
422
|
# can be used as an argument for establish_connection, for easily
|
339
423
|
# re-establishing the connection.
|
340
424
|
def remove_connection(klass)
|
341
|
-
pool = @
|
342
|
-
|
343
|
-
|
344
|
-
pool.spec
|
425
|
+
pool = @class_to_pool.delete(klass.name)
|
426
|
+
return nil unless pool
|
427
|
+
|
428
|
+
@connection_pools.delete pool.spec
|
429
|
+
pool.automatic_reconnect = false
|
430
|
+
pool.disconnect!
|
431
|
+
pool.spec.config
|
345
432
|
end
|
346
433
|
|
347
434
|
def retrieve_connection_pool(klass)
|
348
|
-
pool = @
|
435
|
+
pool = @class_to_pool[klass.name]
|
349
436
|
return pool if pool
|
350
437
|
return nil if ActiveRecord::Base == klass
|
351
438
|
retrieve_connection_pool klass.superclass
|
@@ -353,18 +440,48 @@ module ActiveRecord
|
|
353
440
|
end
|
354
441
|
|
355
442
|
class ConnectionManagement
|
443
|
+
class Proxy # :nodoc:
|
444
|
+
attr_reader :body, :testing
|
445
|
+
|
446
|
+
def initialize(body, testing = false)
|
447
|
+
@body = body
|
448
|
+
@testing = testing
|
449
|
+
end
|
450
|
+
|
451
|
+
def method_missing(method_sym, *arguments, &block)
|
452
|
+
@body.send(method_sym, *arguments, &block)
|
453
|
+
end
|
454
|
+
|
455
|
+
def respond_to?(method_sym, include_private = false)
|
456
|
+
super || @body.respond_to?(method_sym)
|
457
|
+
end
|
458
|
+
|
459
|
+
def each(&block)
|
460
|
+
body.each(&block)
|
461
|
+
end
|
462
|
+
|
463
|
+
def close
|
464
|
+
body.close if body.respond_to?(:close)
|
465
|
+
|
466
|
+
# Don't return connection (and perform implicit rollback) if
|
467
|
+
# this request is a part of integration test
|
468
|
+
ActiveRecord::Base.clear_active_connections! unless testing
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
356
472
|
def initialize(app)
|
357
473
|
@app = app
|
358
474
|
end
|
359
475
|
|
360
476
|
def call(env)
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
477
|
+
testing = env.key?('rack.test')
|
478
|
+
|
479
|
+
status, headers, body = @app.call(env)
|
480
|
+
|
481
|
+
[status, headers, Proxy.new(body, testing)]
|
482
|
+
rescue
|
483
|
+
ActiveRecord::Base.clear_active_connections! unless testing
|
484
|
+
raise
|
368
485
|
end
|
369
486
|
end
|
370
487
|
end
|