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,3 +1,5 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
class Base
|
3
5
|
class ConnectionSpecification #:nodoc:
|
@@ -5,12 +7,81 @@ module ActiveRecord
|
|
5
7
|
def initialize (config, adapter_method)
|
6
8
|
@config, @adapter_method = config, adapter_method
|
7
9
|
end
|
10
|
+
|
11
|
+
##
|
12
|
+
# Builds a ConnectionSpecification from user input
|
13
|
+
class Resolver # :nodoc:
|
14
|
+
attr_reader :config, :klass, :configurations
|
15
|
+
|
16
|
+
def initialize(config, configurations)
|
17
|
+
@config = config
|
18
|
+
@configurations = configurations
|
19
|
+
end
|
20
|
+
|
21
|
+
def spec
|
22
|
+
case config
|
23
|
+
when nil
|
24
|
+
raise AdapterNotSpecified unless defined?(Rails.env)
|
25
|
+
resolve_string_connection Rails.env
|
26
|
+
when Symbol, String
|
27
|
+
resolve_string_connection config.to_s
|
28
|
+
when Hash
|
29
|
+
resolve_hash_connection config
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
def resolve_string_connection(spec) # :nodoc:
|
35
|
+
hash = configurations.fetch(spec) do |k|
|
36
|
+
connection_url_to_hash(k)
|
37
|
+
end
|
38
|
+
|
39
|
+
raise(AdapterNotSpecified, "#{spec} database is not configured") unless hash
|
40
|
+
|
41
|
+
resolve_hash_connection hash
|
42
|
+
end
|
43
|
+
|
44
|
+
def resolve_hash_connection(spec) # :nodoc:
|
45
|
+
spec = spec.symbolize_keys
|
46
|
+
|
47
|
+
raise(AdapterNotSpecified, "database configuration does not specify adapter") unless spec.key?(:adapter)
|
48
|
+
|
49
|
+
begin
|
50
|
+
require "active_record/connection_adapters/#{spec[:adapter]}_adapter"
|
51
|
+
rescue LoadError => e
|
52
|
+
raise LoadError, "Please install the #{spec[:adapter]} adapter: `gem install activerecord-#{spec[:adapter]}-adapter` (#{e.message})", e.backtrace
|
53
|
+
end
|
54
|
+
|
55
|
+
adapter_method = "#{spec[:adapter]}_connection"
|
56
|
+
|
57
|
+
ConnectionSpecification.new(spec, adapter_method)
|
58
|
+
end
|
59
|
+
|
60
|
+
def connection_url_to_hash(url) # :nodoc:
|
61
|
+
config = URI.parse url
|
62
|
+
adapter = config.scheme
|
63
|
+
adapter = "postgresql" if adapter == "postgres"
|
64
|
+
spec = { :adapter => adapter,
|
65
|
+
:username => config.user,
|
66
|
+
:password => config.password,
|
67
|
+
:port => config.port,
|
68
|
+
:database => config.path.sub(%r{^/},""),
|
69
|
+
:host => config.host }
|
70
|
+
spec.reject!{ |_,value| value.blank? }
|
71
|
+
spec.map { |key,value| spec[key] = URI.unescape(value) if value.is_a?(String) }
|
72
|
+
if config.query
|
73
|
+
options = Hash[config.query.split("&").map{ |pair| pair.split("=") }].symbolize_keys
|
74
|
+
spec.merge!(options)
|
75
|
+
end
|
76
|
+
spec
|
77
|
+
end
|
78
|
+
end
|
8
79
|
end
|
9
80
|
|
10
81
|
##
|
11
82
|
# :singleton-method:
|
12
83
|
# The connection handler
|
13
|
-
class_attribute :connection_handler
|
84
|
+
class_attribute :connection_handler, :instance_writer => false
|
14
85
|
self.connection_handler = ConnectionAdapters::ConnectionHandler.new
|
15
86
|
|
16
87
|
# Returns the connection currently associated with the class. This can
|
@@ -46,84 +117,61 @@ module ActiveRecord
|
|
46
117
|
# "database" => "path/to/dbfile"
|
47
118
|
# )
|
48
119
|
#
|
120
|
+
# Or a URL:
|
121
|
+
#
|
122
|
+
# ActiveRecord::Base.establish_connection(
|
123
|
+
# "postgres://myuser:mypass@localhost/somedatabase"
|
124
|
+
# )
|
125
|
+
#
|
49
126
|
# The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError
|
50
127
|
# may be returned on an error.
|
51
|
-
def self.establish_connection(spec =
|
52
|
-
|
53
|
-
|
54
|
-
raise AdapterNotSpecified unless defined? RAILS_ENV
|
55
|
-
establish_connection(RAILS_ENV)
|
56
|
-
when ConnectionSpecification
|
57
|
-
self.connection_handler.establish_connection(name, spec)
|
58
|
-
when Symbol, String
|
59
|
-
if configuration = configurations[spec.to_s]
|
60
|
-
establish_connection(configuration)
|
61
|
-
else
|
62
|
-
raise AdapterNotSpecified, "#{spec} database is not configured"
|
63
|
-
end
|
64
|
-
else
|
65
|
-
spec = spec.symbolize_keys
|
66
|
-
unless spec.key?(:adapter) then raise AdapterNotSpecified, "database configuration does not specify adapter" end
|
67
|
-
|
68
|
-
begin
|
69
|
-
require 'rubygems'
|
70
|
-
gem "activerecord-#{spec[:adapter]}-adapter"
|
71
|
-
require "active_record/connection_adapters/#{spec[:adapter]}_adapter"
|
72
|
-
rescue LoadError
|
73
|
-
begin
|
74
|
-
require "active_record/connection_adapters/#{spec[:adapter]}_adapter"
|
75
|
-
rescue LoadError
|
76
|
-
raise "Please install the #{spec[:adapter]} adapter: `gem install activerecord-#{spec[:adapter]}-adapter` (#{$!})"
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
adapter_method = "#{spec[:adapter]}_connection"
|
81
|
-
if !respond_to?(adapter_method)
|
82
|
-
raise AdapterNotFound, "database configuration specifies nonexistent #{spec[:adapter]} adapter"
|
83
|
-
end
|
128
|
+
def self.establish_connection(spec = ENV["DATABASE_URL"])
|
129
|
+
resolver = ConnectionSpecification::Resolver.new spec, configurations
|
130
|
+
spec = resolver.spec
|
84
131
|
|
85
|
-
|
86
|
-
|
132
|
+
unless respond_to?(spec.adapter_method)
|
133
|
+
raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"
|
87
134
|
end
|
135
|
+
|
136
|
+
remove_connection
|
137
|
+
connection_handler.establish_connection name, spec
|
88
138
|
end
|
89
139
|
|
90
140
|
class << self
|
91
|
-
#
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
# Deprecated and no longer has any effect.
|
97
|
-
def allow_concurrency=(flag)
|
98
|
-
ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_concurrency= has been deprecated and no longer has any effect. Please remove all references to allow_concurrency=.")
|
141
|
+
# Returns the connection currently associated with the class. This can
|
142
|
+
# also be used to "borrow" the connection to do database work unrelated
|
143
|
+
# to any of the specific Active Records.
|
144
|
+
def connection
|
145
|
+
retrieve_connection
|
99
146
|
end
|
100
147
|
|
101
|
-
|
102
|
-
|
103
|
-
ActiveSupport::Deprecation.warn("ActiveRecord::Base.verification_timeout has been deprecated and no longer has any effect. Please remove all references to verification_timeout.")
|
148
|
+
def connection_id
|
149
|
+
Thread.current['ActiveRecord::Base.connection_id']
|
104
150
|
end
|
105
151
|
|
106
|
-
|
107
|
-
|
108
|
-
ActiveSupport::Deprecation.warn("ActiveRecord::Base.verification_timeout= has been deprecated and no longer has any effect. Please remove all references to verification_timeout=.")
|
152
|
+
def connection_id=(connection_id)
|
153
|
+
Thread.current['ActiveRecord::Base.connection_id'] = connection_id
|
109
154
|
end
|
110
155
|
|
111
|
-
# Returns the
|
112
|
-
#
|
113
|
-
#
|
114
|
-
|
115
|
-
|
156
|
+
# Returns the configuration of the associated connection as a hash:
|
157
|
+
#
|
158
|
+
# ActiveRecord::Base.connection_config
|
159
|
+
# # => {:pool=>5, :timeout=>5000, :database=>"db/development.sqlite3", :adapter=>"sqlite3"}
|
160
|
+
#
|
161
|
+
# Please use only for reading.
|
162
|
+
def connection_config
|
163
|
+
connection_pool.spec.config
|
116
164
|
end
|
117
165
|
|
118
166
|
def connection_pool
|
119
|
-
connection_handler.retrieve_connection_pool(self)
|
167
|
+
connection_handler.retrieve_connection_pool(self) or raise ConnectionNotEstablished
|
120
168
|
end
|
121
169
|
|
122
170
|
def retrieve_connection
|
123
171
|
connection_handler.retrieve_connection(self)
|
124
172
|
end
|
125
173
|
|
126
|
-
# Returns true if
|
174
|
+
# Returns true if Active Record is connected.
|
127
175
|
def connected?
|
128
176
|
connection_handler.connected?(self)
|
129
177
|
end
|
@@ -132,7 +180,11 @@ module ActiveRecord
|
|
132
180
|
connection_handler.remove_connection(klass)
|
133
181
|
end
|
134
182
|
|
135
|
-
|
183
|
+
def clear_active_connections!
|
184
|
+
connection_handler.clear_active_connections!
|
185
|
+
end
|
186
|
+
|
187
|
+
delegate :clear_reloadable_connections!,
|
136
188
|
:clear_all_connections!,:verify_active_connections!, :to => :connection_handler
|
137
189
|
end
|
138
190
|
end
|
@@ -2,52 +2,53 @@ module ActiveRecord
|
|
2
2
|
module ConnectionAdapters # :nodoc:
|
3
3
|
module DatabaseLimits
|
4
4
|
|
5
|
-
# the maximum length of a table alias
|
5
|
+
# Returns the maximum length of a table alias.
|
6
6
|
def table_alias_length
|
7
7
|
255
|
8
8
|
end
|
9
9
|
|
10
|
-
# the maximum length of a column name
|
10
|
+
# Returns the maximum length of a column name.
|
11
11
|
def column_name_length
|
12
12
|
64
|
13
13
|
end
|
14
14
|
|
15
|
-
# the maximum length of a table name
|
15
|
+
# Returns the maximum length of a table name.
|
16
16
|
def table_name_length
|
17
17
|
64
|
18
18
|
end
|
19
19
|
|
20
|
-
# the maximum length of an index name
|
20
|
+
# Returns the maximum length of an index name.
|
21
21
|
def index_name_length
|
22
22
|
64
|
23
23
|
end
|
24
24
|
|
25
|
-
# the maximum number of columns per table
|
25
|
+
# Returns the maximum number of columns per table.
|
26
26
|
def columns_per_table
|
27
27
|
1024
|
28
28
|
end
|
29
29
|
|
30
|
-
# the maximum number of indexes per table
|
30
|
+
# Returns the maximum number of indexes per table.
|
31
31
|
def indexes_per_table
|
32
32
|
16
|
33
33
|
end
|
34
34
|
|
35
|
-
# the maximum number of columns in a multicolumn index
|
35
|
+
# Returns the maximum number of columns in a multicolumn index.
|
36
36
|
def columns_per_multicolumn_index
|
37
37
|
16
|
38
38
|
end
|
39
39
|
|
40
|
-
# the maximum number of elements in an IN (x,y,z) clause
|
40
|
+
# Returns the maximum number of elements in an IN (x,y,z) clause.
|
41
|
+
# nil means no limit.
|
41
42
|
def in_clause_length
|
42
|
-
|
43
|
+
nil
|
43
44
|
end
|
44
45
|
|
45
|
-
# the maximum length of
|
46
|
+
# Returns the maximum length of an SQL query.
|
46
47
|
def sql_query_length
|
47
48
|
1048575
|
48
49
|
end
|
49
50
|
|
50
|
-
# maximum number of joins in a single query
|
51
|
+
# Returns maximum number of joins in a single query.
|
51
52
|
def joins_per_query
|
52
53
|
256
|
53
54
|
end
|
@@ -1,30 +1,41 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module ConnectionAdapters # :nodoc:
|
3
3
|
module DatabaseStatements
|
4
|
+
# Converts an arel AST to SQL
|
5
|
+
def to_sql(arel, binds = [])
|
6
|
+
if arel.respond_to?(:ast)
|
7
|
+
visitor.accept(arel.ast) do
|
8
|
+
quote(*binds.shift.reverse)
|
9
|
+
end
|
10
|
+
else
|
11
|
+
arel
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
4
15
|
# Returns an array of record hashes with the column names as keys and
|
5
16
|
# column values as values.
|
6
|
-
def select_all(
|
7
|
-
select(
|
17
|
+
def select_all(arel, name = nil, binds = [])
|
18
|
+
select(to_sql(arel, binds), name, binds)
|
8
19
|
end
|
9
20
|
|
10
21
|
# Returns a record hash with the column names as keys and column values
|
11
22
|
# as values.
|
12
|
-
def select_one(
|
13
|
-
result = select_all(
|
23
|
+
def select_one(arel, name = nil)
|
24
|
+
result = select_all(arel, name)
|
14
25
|
result.first if result
|
15
26
|
end
|
16
27
|
|
17
28
|
# Returns a single value from a record
|
18
|
-
def select_value(
|
19
|
-
if result = select_one(
|
29
|
+
def select_value(arel, name = nil)
|
30
|
+
if result = select_one(arel, name)
|
20
31
|
result.values.first
|
21
32
|
end
|
22
33
|
end
|
23
34
|
|
24
35
|
# Returns an array of the values of the first column in a select:
|
25
36
|
# select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
|
26
|
-
def select_values(
|
27
|
-
result = select_rows(
|
37
|
+
def select_values(arel, name = nil)
|
38
|
+
result = select_rows(to_sql(arel, []), name)
|
28
39
|
result.map { |v| v[0] }
|
29
40
|
end
|
30
41
|
|
@@ -35,25 +46,61 @@ module ActiveRecord
|
|
35
46
|
undef_method :select_rows
|
36
47
|
|
37
48
|
# Executes the SQL statement in the context of this connection.
|
38
|
-
def execute(sql, name = nil
|
49
|
+
def execute(sql, name = nil)
|
39
50
|
end
|
40
51
|
undef_method :execute
|
41
52
|
|
53
|
+
# Executes +sql+ statement in the context of this connection using
|
54
|
+
# +binds+ as the bind substitutes. +name+ is logged along with
|
55
|
+
# the executed +sql+ statement.
|
56
|
+
def exec_query(sql, name = 'SQL', binds = [])
|
57
|
+
end
|
58
|
+
|
59
|
+
# Executes insert +sql+ statement in the context of this connection using
|
60
|
+
# +binds+ as the bind substitutes. +name+ is the logged along with
|
61
|
+
# the executed +sql+ statement.
|
62
|
+
def exec_insert(sql, name, binds)
|
63
|
+
exec_query(sql, name, binds)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Executes delete +sql+ statement in the context of this connection using
|
67
|
+
# +binds+ as the bind substitutes. +name+ is the logged along with
|
68
|
+
# the executed +sql+ statement.
|
69
|
+
def exec_delete(sql, name, binds)
|
70
|
+
exec_query(sql, name, binds)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Executes update +sql+ statement in the context of this connection using
|
74
|
+
# +binds+ as the bind substitutes. +name+ is the logged along with
|
75
|
+
# the executed +sql+ statement.
|
76
|
+
def exec_update(sql, name, binds)
|
77
|
+
exec_query(sql, name, binds)
|
78
|
+
end
|
79
|
+
|
42
80
|
# Returns the last auto-generated ID from the affected table.
|
43
|
-
|
44
|
-
|
81
|
+
#
|
82
|
+
# +id_value+ will be returned unless the value is nil, in
|
83
|
+
# which case the database will attempt to calculate the last inserted
|
84
|
+
# id and return that value.
|
85
|
+
#
|
86
|
+
# If the next id was calculated in advance (as in Oracle), it should be
|
87
|
+
# passed in as +id_value+.
|
88
|
+
def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
|
89
|
+
sql, binds = sql_for_insert(to_sql(arel, binds), pk, id_value, sequence_name, binds)
|
90
|
+
value = exec_insert(sql, name, binds)
|
91
|
+
id_value || last_inserted_id(value)
|
45
92
|
end
|
46
93
|
|
47
94
|
# Executes the update statement and returns the number of rows affected.
|
48
|
-
def update(
|
49
|
-
|
95
|
+
def update(arel, name = nil, binds = [])
|
96
|
+
exec_update(to_sql(arel, binds), name, binds)
|
50
97
|
end
|
51
98
|
|
52
99
|
# Executes the delete statement and returns the number of rows affected.
|
53
|
-
def delete(
|
54
|
-
|
100
|
+
def delete(arel, name = nil, binds = [])
|
101
|
+
exec_delete(to_sql(arel, binds), name, binds)
|
55
102
|
end
|
56
|
-
|
103
|
+
|
57
104
|
# Checks whether there is currently no transaction active. This is done
|
58
105
|
# by querying the database driver, and does not use the transaction
|
59
106
|
# house-keeping information recorded by #increment_open_transactions and
|
@@ -68,6 +115,12 @@ module ActiveRecord
|
|
68
115
|
nil
|
69
116
|
end
|
70
117
|
|
118
|
+
# Returns +true+ when the connection adapter supports prepared statement
|
119
|
+
# caching, otherwise returns +false+
|
120
|
+
def supports_statement_cache?
|
121
|
+
false
|
122
|
+
end
|
123
|
+
|
71
124
|
# Runs the given block in a database transaction, and returns the result
|
72
125
|
# of the block.
|
73
126
|
#
|
@@ -79,7 +132,7 @@ module ActiveRecord
|
|
79
132
|
#
|
80
133
|
# In order to get around this problem, #transaction will emulate the effect
|
81
134
|
# of nested transactions, by using savepoints:
|
82
|
-
# http://dev.mysql.com/doc/refman/5.0/en/
|
135
|
+
# http://dev.mysql.com/doc/refman/5.0/en/savepoint.html
|
83
136
|
# Savepoints are supported by MySQL and PostgreSQL, but not SQLite3.
|
84
137
|
#
|
85
138
|
# It is safe to call this method if a database transaction is already open,
|
@@ -113,7 +166,7 @@ module ActiveRecord
|
|
113
166
|
def transaction(options = {})
|
114
167
|
options.assert_valid_keys :requires_new, :joinable
|
115
168
|
|
116
|
-
last_transaction_joinable = @transaction_joinable
|
169
|
+
last_transaction_joinable = defined?(@transaction_joinable) ? @transaction_joinable : nil
|
117
170
|
if options.has_key?(:joinable)
|
118
171
|
@transaction_joinable = options[:joinable]
|
119
172
|
else
|
@@ -122,6 +175,8 @@ module ActiveRecord
|
|
122
175
|
requires_new = options[:requires_new] || !last_transaction_joinable
|
123
176
|
|
124
177
|
transaction_open = false
|
178
|
+
@_current_transaction_records ||= []
|
179
|
+
|
125
180
|
begin
|
126
181
|
if block_given?
|
127
182
|
if requires_new || open_transactions == 0
|
@@ -132,6 +187,7 @@ module ActiveRecord
|
|
132
187
|
end
|
133
188
|
increment_open_transactions
|
134
189
|
transaction_open = true
|
190
|
+
@_current_transaction_records.push([])
|
135
191
|
end
|
136
192
|
yield
|
137
193
|
end
|
@@ -141,8 +197,10 @@ module ActiveRecord
|
|
141
197
|
decrement_open_transactions
|
142
198
|
if open_transactions == 0
|
143
199
|
rollback_db_transaction
|
200
|
+
rollback_transaction_records(true)
|
144
201
|
else
|
145
202
|
rollback_to_savepoint
|
203
|
+
rollback_transaction_records(false)
|
146
204
|
end
|
147
205
|
end
|
148
206
|
raise unless database_transaction_rollback.is_a?(ActiveRecord::Rollback)
|
@@ -157,20 +215,35 @@ module ActiveRecord
|
|
157
215
|
begin
|
158
216
|
if open_transactions == 0
|
159
217
|
commit_db_transaction
|
218
|
+
commit_transaction_records
|
160
219
|
else
|
161
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
|
162
226
|
end
|
163
227
|
rescue Exception => database_transaction_rollback
|
164
228
|
if open_transactions == 0
|
165
229
|
rollback_db_transaction
|
230
|
+
rollback_transaction_records(true)
|
166
231
|
else
|
167
232
|
rollback_to_savepoint
|
233
|
+
rollback_transaction_records(false)
|
168
234
|
end
|
169
235
|
raise
|
170
236
|
end
|
171
237
|
end
|
172
238
|
end
|
173
|
-
|
239
|
+
|
240
|
+
# Register a record with the current transaction so that its after_commit and after_rollback callbacks
|
241
|
+
# can be called.
|
242
|
+
def add_transaction_record(record)
|
243
|
+
last_batch = @_current_transaction_records.last
|
244
|
+
last_batch << record if last_batch
|
245
|
+
end
|
246
|
+
|
174
247
|
# Begins the transaction (and turns off auto-committing).
|
175
248
|
def begin_db_transaction() end
|
176
249
|
|
@@ -181,62 +254,31 @@ module ActiveRecord
|
|
181
254
|
# done if the transaction block raises an exception or returns false.
|
182
255
|
def rollback_db_transaction() end
|
183
256
|
|
184
|
-
# Alias for <tt>add_limit_offset!</tt>.
|
185
|
-
def add_limit!(sql, options)
|
186
|
-
add_limit_offset!(sql, options) if options
|
187
|
-
end
|
188
|
-
|
189
|
-
# Appends +LIMIT+ and +OFFSET+ options to an SQL statement, or some SQL
|
190
|
-
# fragment that has the same semantics as LIMIT and OFFSET.
|
191
|
-
#
|
192
|
-
# +options+ must be a Hash which contains a +:limit+ option (required)
|
193
|
-
# and an +:offset+ option (optional).
|
194
|
-
#
|
195
|
-
# This method *modifies* the +sql+ parameter.
|
196
|
-
#
|
197
|
-
# ===== Examples
|
198
|
-
# add_limit_offset!('SELECT * FROM suppliers', {:limit => 10, :offset => 50})
|
199
|
-
# generates
|
200
|
-
# SELECT * FROM suppliers LIMIT 10 OFFSET 50
|
201
|
-
def add_limit_offset!(sql, options)
|
202
|
-
if limit = options[:limit]
|
203
|
-
sql << " LIMIT #{sanitize_limit(limit)}"
|
204
|
-
if offset = options[:offset]
|
205
|
-
sql << " OFFSET #{offset.to_i}"
|
206
|
-
end
|
207
|
-
end
|
208
|
-
sql
|
209
|
-
end
|
210
|
-
|
211
|
-
# Appends a locking clause to an SQL statement.
|
212
|
-
# This method *modifies* the +sql+ parameter.
|
213
|
-
# # SELECT * FROM suppliers FOR UPDATE
|
214
|
-
# add_lock! 'SELECT * FROM suppliers', :lock => true
|
215
|
-
# add_lock! 'SELECT * FROM suppliers', :lock => ' FOR UPDATE'
|
216
|
-
def add_lock!(sql, options)
|
217
|
-
case lock = options[:lock]
|
218
|
-
when true; sql << ' FOR UPDATE'
|
219
|
-
when String; sql << " #{lock}"
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
257
|
def default_sequence_name(table, column)
|
224
258
|
nil
|
225
259
|
end
|
226
260
|
|
227
261
|
# Set the sequence to the max value of the table's column.
|
228
262
|
def reset_sequence!(table, column, sequence = nil)
|
229
|
-
# Do nothing by default.
|
263
|
+
# Do nothing by default. Implement for PostgreSQL, Oracle, ...
|
230
264
|
end
|
231
265
|
|
232
266
|
# Inserts the given fixture into the table. Overridden in adapters that require
|
233
267
|
# something beyond a simple insert (eg. Oracle).
|
234
268
|
def insert_fixture(fixture, table_name)
|
235
|
-
|
269
|
+
columns = schema_cache.columns_hash(table_name)
|
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'
|
236
278
|
end
|
237
279
|
|
238
|
-
def
|
239
|
-
"
|
280
|
+
def empty_insert_statement_value
|
281
|
+
"VALUES(DEFAULT)"
|
240
282
|
end
|
241
283
|
|
242
284
|
def case_sensitive_equality_operator
|
@@ -247,10 +289,39 @@ module ActiveRecord
|
|
247
289
|
"WHERE #{quoted_primary_key} IN (SELECT #{quoted_primary_key} FROM #{quoted_table_name} #{where_sql})"
|
248
290
|
end
|
249
291
|
|
292
|
+
# Sanitizes the given LIMIT parameter in order to prevent SQL injection.
|
293
|
+
#
|
294
|
+
# The +limit+ may be anything that can evaluate to a string via #to_s. It
|
295
|
+
# should look like an integer, or a comma-delimited list of integers, or
|
296
|
+
# an Arel SQL literal.
|
297
|
+
#
|
298
|
+
# 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
|
+
def sanitize_limit(limit)
|
302
|
+
if limit.is_a?(Integer) || limit.is_a?(Arel::Nodes::SqlLiteral)
|
303
|
+
limit
|
304
|
+
elsif limit.to_s =~ /,/
|
305
|
+
Arel.sql limit.to_s.split(',').map{ |i| Integer(i) }.join(',')
|
306
|
+
else
|
307
|
+
Integer(limit)
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
# The default strategy for an UPDATE with joins is to use a subquery. This doesn't work
|
312
|
+
# on mysql (even when aliasing the tables), but mysql allows using JOIN directly in
|
313
|
+
# an UPDATE statement, so in the mysql adapters we redefine this to do that.
|
314
|
+
def join_to_update(update, select) #:nodoc:
|
315
|
+
subselect = select.clone
|
316
|
+
subselect.projections = [update.key]
|
317
|
+
|
318
|
+
update.where update.key.in(subselect)
|
319
|
+
end
|
320
|
+
|
250
321
|
protected
|
251
322
|
# Returns an array of record hashes with the column names as keys and
|
252
323
|
# column values as values.
|
253
|
-
def select(sql, name = nil)
|
324
|
+
def select(sql, name = nil, binds = [])
|
254
325
|
end
|
255
326
|
undef_method :select
|
256
327
|
|
@@ -270,20 +341,50 @@ module ActiveRecord
|
|
270
341
|
update_sql(sql, name)
|
271
342
|
end
|
272
343
|
|
273
|
-
#
|
274
|
-
#
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
# string which contains a comma-delimited list of integers.
|
280
|
-
def sanitize_limit(limit)
|
281
|
-
if limit.to_s =~ /,/
|
282
|
-
limit.to_s.split(',').map{ |i| i.to_i }.join(',')
|
344
|
+
# Send a rollback message to all records after they have been rolled back. If rollback
|
345
|
+
# is false, only rollback records since the last save point.
|
346
|
+
def rollback_transaction_records(rollback)
|
347
|
+
if rollback
|
348
|
+
records = @_current_transaction_records.flatten
|
349
|
+
@_current_transaction_records.clear
|
283
350
|
else
|
284
|
-
|
351
|
+
records = @_current_transaction_records.pop
|
352
|
+
end
|
353
|
+
|
354
|
+
unless records.blank?
|
355
|
+
records.uniq.each do |record|
|
356
|
+
begin
|
357
|
+
record.rolledback!(rollback)
|
358
|
+
rescue Exception => e
|
359
|
+
record.logger.error(e) if record.respond_to?(:logger) && record.logger
|
360
|
+
end
|
361
|
+
end
|
285
362
|
end
|
286
363
|
end
|
364
|
+
|
365
|
+
# Send a commit message to all records after they have been committed.
|
366
|
+
def commit_transaction_records
|
367
|
+
records = @_current_transaction_records.flatten
|
368
|
+
@_current_transaction_records.clear
|
369
|
+
unless records.blank?
|
370
|
+
records.uniq.each do |record|
|
371
|
+
begin
|
372
|
+
record.committed!
|
373
|
+
rescue Exception => e
|
374
|
+
record.logger.error(e) if record.respond_to?(:logger) && record.logger
|
375
|
+
end
|
376
|
+
end
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
def sql_for_insert(sql, pk, id_value, sequence_name, binds)
|
381
|
+
[sql, binds]
|
382
|
+
end
|
383
|
+
|
384
|
+
def last_inserted_id(result)
|
385
|
+
row = result.rows.first
|
386
|
+
row && row.first
|
387
|
+
end
|
287
388
|
end
|
288
389
|
end
|
289
390
|
end
|