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,46 +1,20 @@
|
|
1
|
-
require 'active_record/connection_adapters/
|
2
|
-
require '
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
# C driver >= 2.7 returns null values in each_hash
|
15
|
-
if Mysql.const_defined?(:VERSION) && (Mysql::VERSION.is_a?(String) || Mysql::VERSION >= 20700)
|
16
|
-
target.class_eval <<-'end_eval'
|
17
|
-
def all_hashes # def all_hashes
|
18
|
-
rows = [] # rows = []
|
19
|
-
each_hash { |row| rows << row } # each_hash { |row| rows << row }
|
20
|
-
rows # rows
|
21
|
-
end # end
|
22
|
-
end_eval
|
23
|
-
|
24
|
-
# adapters before 2.7 don't have a version constant
|
25
|
-
# and don't return null values in each_hash
|
26
|
-
else
|
27
|
-
target.class_eval <<-'end_eval'
|
28
|
-
def all_hashes # def all_hashes
|
29
|
-
rows = [] # rows = []
|
30
|
-
all_fields = fetch_fields.inject({}) { |fields, f| # all_fields = fetch_fields.inject({}) { |fields, f|
|
31
|
-
fields[f.name] = nil; fields # fields[f.name] = nil; fields
|
32
|
-
} # }
|
33
|
-
each_hash { |row| rows << all_fields.dup.update(row) } # each_hash { |row| rows << all_fields.dup.update(row) }
|
34
|
-
rows # rows
|
35
|
-
end # end
|
36
|
-
end_eval
|
37
|
-
end
|
38
|
-
|
39
|
-
unless target.instance_methods.include?('all_hashes') ||
|
40
|
-
target.instance_methods.include?(:all_hashes)
|
41
|
-
raise "Failed to defined #{target.name}#all_hashes method. Mysql::VERSION = #{Mysql::VERSION.inspect}"
|
1
|
+
require 'active_record/connection_adapters/abstract_mysql_adapter'
|
2
|
+
require 'active_record/connection_adapters/statement_pool'
|
3
|
+
require 'active_support/core_ext/hash/keys'
|
4
|
+
|
5
|
+
gem 'mysql', '~> 2.8'
|
6
|
+
require 'mysql'
|
7
|
+
|
8
|
+
class Mysql
|
9
|
+
class Time
|
10
|
+
###
|
11
|
+
# This monkey patch is for test_additional_columns_from_join_table
|
12
|
+
def to_date
|
13
|
+
Date.new(year, month, day)
|
42
14
|
end
|
43
15
|
end
|
16
|
+
class Stmt; include Enumerable end
|
17
|
+
class Result; include Enumerable end
|
44
18
|
end
|
45
19
|
|
46
20
|
module ActiveRecord
|
@@ -55,90 +29,17 @@ module ActiveRecord
|
|
55
29
|
password = config[:password].to_s
|
56
30
|
database = config[:database]
|
57
31
|
|
58
|
-
# Require the MySQL driver and define Mysql::Result.all_hashes
|
59
|
-
unless defined? Mysql
|
60
|
-
begin
|
61
|
-
require_library_or_gem('mysql')
|
62
|
-
rescue LoadError
|
63
|
-
$stderr.puts '!!! The bundled mysql.rb driver has been removed from Rails 2.2. Please install the mysql gem and try again: gem install mysql.'
|
64
|
-
raise
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
MysqlCompat.define_all_hashes_method!
|
69
|
-
|
70
32
|
mysql = Mysql.init
|
71
33
|
mysql.ssl_set(config[:sslkey], config[:sslcert], config[:sslca], config[:sslcapath], config[:sslcipher]) if config[:sslca] || config[:sslkey]
|
72
34
|
|
73
35
|
default_flags = Mysql.const_defined?(:CLIENT_MULTI_RESULTS) ? Mysql::CLIENT_MULTI_RESULTS : 0
|
36
|
+
default_flags |= Mysql::CLIENT_FOUND_ROWS if Mysql.const_defined?(:CLIENT_FOUND_ROWS)
|
74
37
|
options = [host, username, password, database, port, socket, default_flags]
|
75
38
|
ConnectionAdapters::MysqlAdapter.new(mysql, logger, options, config)
|
76
39
|
end
|
77
40
|
end
|
78
41
|
|
79
42
|
module ConnectionAdapters
|
80
|
-
class MysqlColumn < Column #:nodoc:
|
81
|
-
def extract_default(default)
|
82
|
-
if sql_type =~ /blob/i || type == :text
|
83
|
-
if default.blank?
|
84
|
-
return null ? nil : ''
|
85
|
-
else
|
86
|
-
raise ArgumentError, "#{type} columns cannot have a default value: #{default.inspect}"
|
87
|
-
end
|
88
|
-
elsif missing_default_forged_as_empty_string?(default)
|
89
|
-
nil
|
90
|
-
else
|
91
|
-
super
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def has_default?
|
96
|
-
return false if sql_type =~ /blob/i || type == :text #mysql forbids defaults on blob and text columns
|
97
|
-
super
|
98
|
-
end
|
99
|
-
|
100
|
-
private
|
101
|
-
def simplified_type(field_type)
|
102
|
-
return :boolean if MysqlAdapter.emulate_booleans && field_type.downcase.index("tinyint(1)")
|
103
|
-
return :string if field_type =~ /enum/i
|
104
|
-
super
|
105
|
-
end
|
106
|
-
|
107
|
-
def extract_limit(sql_type)
|
108
|
-
case sql_type
|
109
|
-
when /blob|text/i
|
110
|
-
case sql_type
|
111
|
-
when /tiny/i
|
112
|
-
255
|
113
|
-
when /medium/i
|
114
|
-
16777215
|
115
|
-
when /long/i
|
116
|
-
2147483647 # mysql only allows 2^31-1, not 2^32-1, somewhat inconsistently with the tiny/medium/normal cases
|
117
|
-
else
|
118
|
-
super # we could return 65535 here, but we leave it undecorated by default
|
119
|
-
end
|
120
|
-
when /^bigint/i; 8
|
121
|
-
when /^int/i; 4
|
122
|
-
when /^mediumint/i; 3
|
123
|
-
when /^smallint/i; 2
|
124
|
-
when /^tinyint/i; 1
|
125
|
-
else
|
126
|
-
super
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
# MySQL misreports NOT NULL column default when none is given.
|
131
|
-
# We can't detect this for columns which may have a legitimate ''
|
132
|
-
# default (string) but we can for others (integer, datetime, boolean,
|
133
|
-
# and the rest).
|
134
|
-
#
|
135
|
-
# Test whether the column has default '', is not null, and is not
|
136
|
-
# a type allowing default ''.
|
137
|
-
def missing_default_forged_as_empty_string?(default)
|
138
|
-
type != :string && !null && default == ''
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
43
|
# The MySQL adapter will work with both Ruby/MySQL, which is a Ruby-based MySQL adapter that comes bundled with Active Record, and with
|
143
44
|
# the faster C-based MySQL/Ruby adapter (available both as a gem and from http://www.tmtm.org/en/mysql/ruby/).
|
144
45
|
#
|
@@ -158,116 +59,115 @@ module ActiveRecord
|
|
158
59
|
# * <tt>:sslcapath</tt> - Necessary to use MySQL with an SSL connection.
|
159
60
|
# * <tt>:sslcipher</tt> - Necessary to use MySQL with an SSL connection.
|
160
61
|
#
|
161
|
-
class MysqlAdapter <
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
LOST_CONNECTION_ERROR_MESSAGES = [
|
177
|
-
"Server shutdown in progress",
|
178
|
-
"Broken pipe",
|
179
|
-
"Lost connection to MySQL server during query",
|
180
|
-
"MySQL server has gone away" ]
|
181
|
-
|
182
|
-
QUOTED_TRUE, QUOTED_FALSE = '1'.freeze, '0'.freeze
|
183
|
-
|
184
|
-
NATIVE_DATABASE_TYPES = {
|
185
|
-
:primary_key => "int(11) DEFAULT NULL auto_increment PRIMARY KEY".freeze,
|
186
|
-
:string => { :name => "varchar", :limit => 255 },
|
187
|
-
:text => { :name => "text" },
|
188
|
-
:integer => { :name => "int", :limit => 4 },
|
189
|
-
:float => { :name => "float" },
|
190
|
-
:decimal => { :name => "decimal" },
|
191
|
-
:datetime => { :name => "datetime" },
|
192
|
-
:timestamp => { :name => "datetime" },
|
193
|
-
:time => { :name => "time" },
|
194
|
-
:date => { :name => "date" },
|
195
|
-
:binary => { :name => "blob" },
|
196
|
-
:boolean => { :name => "tinyint", :limit => 1 }
|
197
|
-
}
|
62
|
+
class MysqlAdapter < AbstractMysqlAdapter
|
63
|
+
|
64
|
+
class Column < AbstractMysqlAdapter::Column #:nodoc:
|
65
|
+
def self.string_to_time(value)
|
66
|
+
return super unless Mysql::Time === value
|
67
|
+
new_time(
|
68
|
+
value.year,
|
69
|
+
value.month,
|
70
|
+
value.day,
|
71
|
+
value.hour,
|
72
|
+
value.minute,
|
73
|
+
value.second,
|
74
|
+
value.second_part)
|
75
|
+
end
|
198
76
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
connect
|
204
|
-
end
|
77
|
+
def self.string_to_dummy_time(v)
|
78
|
+
return super unless Mysql::Time === v
|
79
|
+
new_time(2000, 01, 01, v.hour, v.minute, v.second, v.second_part)
|
80
|
+
end
|
205
81
|
|
206
|
-
|
207
|
-
|
208
|
-
|
82
|
+
def self.string_to_date(v)
|
83
|
+
return super unless Mysql::Time === v
|
84
|
+
new_date(v.year, v.month, v.day)
|
85
|
+
end
|
209
86
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
def supports_primary_key? #:nodoc:
|
215
|
-
true
|
87
|
+
def adapter
|
88
|
+
MysqlAdapter
|
89
|
+
end
|
216
90
|
end
|
217
91
|
|
218
|
-
|
219
|
-
true
|
220
|
-
end
|
92
|
+
ADAPTER_NAME = 'MySQL'
|
221
93
|
|
222
|
-
|
223
|
-
|
224
|
-
|
94
|
+
class StatementPool < ConnectionAdapters::StatementPool
|
95
|
+
def initialize(connection, max = 1000)
|
96
|
+
super
|
97
|
+
@cache = Hash.new { |h,pid| h[pid] = {} }
|
98
|
+
end
|
225
99
|
|
100
|
+
def each(&block); cache.each(&block); end
|
101
|
+
def key?(key); cache.key?(key); end
|
102
|
+
def [](key); cache[key]; end
|
103
|
+
def length; cache.length; end
|
104
|
+
def delete(key); cache.delete(key); end
|
226
105
|
|
227
|
-
|
106
|
+
def []=(sql, key)
|
107
|
+
while @max <= cache.size
|
108
|
+
cache.shift.last[:stmt].close
|
109
|
+
end
|
110
|
+
cache[sql] = key
|
111
|
+
end
|
228
112
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
113
|
+
def clear
|
114
|
+
cache.values.each do |hash|
|
115
|
+
hash[:stmt].close
|
116
|
+
end
|
117
|
+
cache.clear
|
118
|
+
end
|
119
|
+
|
120
|
+
private
|
121
|
+
def cache
|
122
|
+
@cache[$$]
|
237
123
|
end
|
238
124
|
end
|
239
125
|
|
240
|
-
def
|
241
|
-
|
126
|
+
def initialize(connection, logger, connection_options, config)
|
127
|
+
super
|
128
|
+
@statements = StatementPool.new(@connection,
|
129
|
+
config.fetch(:statement_limit) { 1000 })
|
130
|
+
@client_encoding = nil
|
131
|
+
connect
|
242
132
|
end
|
243
133
|
|
244
|
-
|
245
|
-
|
134
|
+
# Returns true, since this connection adapter supports prepared statement
|
135
|
+
# caching.
|
136
|
+
def supports_statement_cache?
|
137
|
+
true
|
246
138
|
end
|
247
139
|
|
248
|
-
|
249
|
-
|
140
|
+
# HELPER METHODS ===========================================
|
141
|
+
|
142
|
+
def each_hash(result) # :nodoc:
|
143
|
+
if block_given?
|
144
|
+
result.each_hash do |row|
|
145
|
+
row.symbolize_keys!
|
146
|
+
yield row
|
147
|
+
end
|
148
|
+
else
|
149
|
+
to_enum(:each_hash, result)
|
150
|
+
end
|
250
151
|
end
|
251
152
|
|
252
|
-
def
|
253
|
-
|
153
|
+
def new_column(field, default, type, null, collation) # :nodoc:
|
154
|
+
Column.new(field, default, type, null, collation)
|
254
155
|
end
|
255
156
|
|
256
|
-
def
|
257
|
-
|
157
|
+
def error_number(exception) # :nodoc:
|
158
|
+
exception.errno if exception.respond_to?(:errno)
|
258
159
|
end
|
259
160
|
|
260
|
-
#
|
161
|
+
# QUOTING ==================================================
|
261
162
|
|
262
|
-
def
|
263
|
-
|
163
|
+
def type_cast(value, column)
|
164
|
+
return super unless value == true || value == false
|
264
165
|
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
end
|
166
|
+
value ? 1 : 0
|
167
|
+
end
|
168
|
+
|
169
|
+
def quote_string(string) #:nodoc:
|
170
|
+
@connection.quote(string)
|
271
171
|
end
|
272
172
|
|
273
173
|
# CONNECTION MANAGEMENT ====================================
|
@@ -291,9 +191,12 @@ module ActiveRecord
|
|
291
191
|
|
292
192
|
def reconnect!
|
293
193
|
disconnect!
|
194
|
+
clear_cache!
|
294
195
|
connect
|
295
196
|
end
|
296
197
|
|
198
|
+
# Disconnects from the database if already connected. Otherwise, this
|
199
|
+
# method does nothing.
|
297
200
|
def disconnect!
|
298
201
|
@connection.close rescue nil
|
299
202
|
end
|
@@ -311,352 +214,228 @@ module ActiveRecord
|
|
311
214
|
|
312
215
|
def select_rows(sql, name = nil)
|
313
216
|
@connection.query_with_result = true
|
314
|
-
|
315
|
-
rows = []
|
316
|
-
result.each { |row| rows << row }
|
317
|
-
result.free
|
217
|
+
rows = exec_query(sql, name).rows
|
318
218
|
@connection.more_results && @connection.next_result # invoking stored procedures with CLIENT_MULTI_RESULTS requires this to tidy up else connection will be dropped
|
319
219
|
rows
|
320
220
|
end
|
321
221
|
|
322
|
-
#
|
323
|
-
def
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
222
|
+
# Clears the prepared statements cache.
|
223
|
+
def clear_cache!
|
224
|
+
@statements.clear
|
225
|
+
end
|
226
|
+
|
227
|
+
if "<3".respond_to?(:encode)
|
228
|
+
# Taken from here:
|
229
|
+
# https://github.com/tmtm/ruby-mysql/blob/master/lib/mysql/charset.rb
|
230
|
+
# Author: TOMITA Masahiro <tommy@tmtm.org>
|
231
|
+
ENCODINGS = {
|
232
|
+
"armscii8" => nil,
|
233
|
+
"ascii" => Encoding::US_ASCII,
|
234
|
+
"big5" => Encoding::Big5,
|
235
|
+
"binary" => Encoding::ASCII_8BIT,
|
236
|
+
"cp1250" => Encoding::Windows_1250,
|
237
|
+
"cp1251" => Encoding::Windows_1251,
|
238
|
+
"cp1256" => Encoding::Windows_1256,
|
239
|
+
"cp1257" => Encoding::Windows_1257,
|
240
|
+
"cp850" => Encoding::CP850,
|
241
|
+
"cp852" => Encoding::CP852,
|
242
|
+
"cp866" => Encoding::IBM866,
|
243
|
+
"cp932" => Encoding::Windows_31J,
|
244
|
+
"dec8" => nil,
|
245
|
+
"eucjpms" => Encoding::EucJP_ms,
|
246
|
+
"euckr" => Encoding::EUC_KR,
|
247
|
+
"gb2312" => Encoding::EUC_CN,
|
248
|
+
"gbk" => Encoding::GBK,
|
249
|
+
"geostd8" => nil,
|
250
|
+
"greek" => Encoding::ISO_8859_7,
|
251
|
+
"hebrew" => Encoding::ISO_8859_8,
|
252
|
+
"hp8" => nil,
|
253
|
+
"keybcs2" => nil,
|
254
|
+
"koi8r" => Encoding::KOI8_R,
|
255
|
+
"koi8u" => Encoding::KOI8_U,
|
256
|
+
"latin1" => Encoding::ISO_8859_1,
|
257
|
+
"latin2" => Encoding::ISO_8859_2,
|
258
|
+
"latin5" => Encoding::ISO_8859_9,
|
259
|
+
"latin7" => Encoding::ISO_8859_13,
|
260
|
+
"macce" => Encoding::MacCentEuro,
|
261
|
+
"macroman" => Encoding::MacRoman,
|
262
|
+
"sjis" => Encoding::SHIFT_JIS,
|
263
|
+
"swe7" => nil,
|
264
|
+
"tis620" => Encoding::TIS_620,
|
265
|
+
"ucs2" => Encoding::UTF_16BE,
|
266
|
+
"ujis" => Encoding::EucJP_ms,
|
267
|
+
"utf8" => Encoding::UTF_8,
|
268
|
+
"utf8mb4" => Encoding::UTF_8,
|
269
|
+
}
|
270
|
+
else
|
271
|
+
ENCODINGS = Hash.new { |h,k| h[k] = k }
|
272
|
+
end
|
273
|
+
|
274
|
+
# Get the client encoding for this database
|
275
|
+
def client_encoding
|
276
|
+
return @client_encoding if @client_encoding
|
277
|
+
|
278
|
+
result = exec_query(
|
279
|
+
"SHOW VARIABLES WHERE Variable_name = 'character_set_client'",
|
280
|
+
'SCHEMA')
|
281
|
+
@client_encoding = ENCODINGS[result.rows.last.last]
|
282
|
+
end
|
283
|
+
|
284
|
+
def exec_query(sql, name = 'SQL', binds = [])
|
285
|
+
# If the configuration sets prepared_statements:false, binds will
|
286
|
+
# always be empty, since the bind variables will have been already
|
287
|
+
# substituted and removed from binds by BindVisitor, so this will
|
288
|
+
# effectively disable prepared statement usage completely.
|
289
|
+
if binds.empty?
|
290
|
+
result_set, affected_rows = exec_without_stmt(sql, name)
|
328
291
|
else
|
329
|
-
|
292
|
+
result_set, affected_rows = exec_stmt(sql, name, binds)
|
330
293
|
end
|
331
|
-
end
|
332
294
|
|
333
|
-
|
334
|
-
super sql, name
|
335
|
-
id_value || @connection.insert_id
|
336
|
-
end
|
337
|
-
|
338
|
-
def update_sql(sql, name = nil) #:nodoc:
|
339
|
-
super
|
340
|
-
@connection.affected_rows
|
341
|
-
end
|
342
|
-
|
343
|
-
def begin_db_transaction #:nodoc:
|
344
|
-
execute "BEGIN"
|
345
|
-
rescue Exception
|
346
|
-
# Transactions aren't supported
|
347
|
-
end
|
348
|
-
|
349
|
-
def commit_db_transaction #:nodoc:
|
350
|
-
execute "COMMIT"
|
351
|
-
rescue Exception
|
352
|
-
# Transactions aren't supported
|
353
|
-
end
|
354
|
-
|
355
|
-
def rollback_db_transaction #:nodoc:
|
356
|
-
execute "ROLLBACK"
|
357
|
-
rescue Exception
|
358
|
-
# Transactions aren't supported
|
359
|
-
end
|
295
|
+
yield affected_rows if block_given?
|
360
296
|
|
361
|
-
|
362
|
-
execute("SAVEPOINT #{current_savepoint_name}")
|
297
|
+
result_set
|
363
298
|
end
|
364
299
|
|
365
|
-
def
|
366
|
-
|
300
|
+
def last_inserted_id(result)
|
301
|
+
@connection.insert_id
|
367
302
|
end
|
368
303
|
|
369
|
-
def
|
370
|
-
|
371
|
-
|
304
|
+
def exec_without_stmt(sql, name = 'SQL') # :nodoc:
|
305
|
+
# Some queries, like SHOW CREATE TABLE don't work through the prepared
|
306
|
+
# statement API. For those queries, we need to use this method. :'(
|
307
|
+
log(sql, name) do
|
308
|
+
result = @connection.query(sql)
|
309
|
+
affected_rows = @connection.affected_rows
|
372
310
|
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
sql << " LIMIT #{limit}"
|
311
|
+
if result
|
312
|
+
cols = result.fetch_fields.map { |field| field.name }
|
313
|
+
result_set = ActiveRecord::Result.new(cols, result.to_a)
|
314
|
+
result.free
|
378
315
|
else
|
379
|
-
|
316
|
+
result_set = ActiveRecord::Result.new([], [])
|
380
317
|
end
|
381
|
-
end
|
382
|
-
end
|
383
318
|
|
384
|
-
|
385
|
-
# SCHEMA STATEMENTS ========================================
|
386
|
-
|
387
|
-
def structure_dump #:nodoc:
|
388
|
-
if supports_views?
|
389
|
-
sql = "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'"
|
390
|
-
else
|
391
|
-
sql = "SHOW TABLES"
|
392
|
-
end
|
393
|
-
|
394
|
-
select_all(sql).inject("") do |structure, table|
|
395
|
-
table.delete('Table_type')
|
396
|
-
structure += select_one("SHOW CREATE TABLE #{quote_table_name(table.to_a.first.last)}")["Create Table"] + ";\n\n"
|
319
|
+
[result_set, affected_rows]
|
397
320
|
end
|
398
321
|
end
|
399
322
|
|
400
|
-
def
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
# Create a new MySQL database with optional <tt>:charset</tt> and <tt>:collation</tt>.
|
406
|
-
# Charset defaults to utf8.
|
407
|
-
#
|
408
|
-
# Example:
|
409
|
-
# create_database 'charset_test', :charset => 'latin1', :collation => 'latin1_bin'
|
410
|
-
# create_database 'matt_development'
|
411
|
-
# create_database 'matt_development', :charset => :big5
|
412
|
-
def create_database(name, options = {})
|
413
|
-
if options[:collation]
|
414
|
-
execute "CREATE DATABASE `#{name}` DEFAULT CHARACTER SET `#{options[:charset] || 'utf8'}` COLLATE `#{options[:collation]}`"
|
415
|
-
else
|
416
|
-
execute "CREATE DATABASE `#{name}` DEFAULT CHARACTER SET `#{options[:charset] || 'utf8'}`"
|
417
|
-
end
|
323
|
+
def execute_and_free(sql, name = nil)
|
324
|
+
result = execute(sql, name)
|
325
|
+
ret = yield result
|
326
|
+
result.free
|
327
|
+
ret
|
418
328
|
end
|
419
329
|
|
420
|
-
def
|
421
|
-
|
330
|
+
def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
|
331
|
+
super sql, name
|
332
|
+
id_value || @connection.insert_id
|
422
333
|
end
|
334
|
+
alias :create :insert_sql
|
423
335
|
|
424
|
-
def
|
425
|
-
|
426
|
-
end
|
336
|
+
def exec_delete(sql, name, binds)
|
337
|
+
affected_rows = 0
|
427
338
|
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
end
|
339
|
+
exec_query(sql, name, binds) do |n|
|
340
|
+
affected_rows = n
|
341
|
+
end
|
432
342
|
|
433
|
-
|
434
|
-
def collation
|
435
|
-
show_variable 'collation_database'
|
343
|
+
affected_rows
|
436
344
|
end
|
345
|
+
alias :exec_update :exec_delete
|
437
346
|
|
438
|
-
def
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
result.free
|
443
|
-
tables
|
347
|
+
def begin_db_transaction #:nodoc:
|
348
|
+
exec_query "BEGIN"
|
349
|
+
rescue Mysql::Error
|
350
|
+
# Transactions aren't supported
|
444
351
|
end
|
445
352
|
|
446
|
-
|
447
|
-
super(table_name, options)
|
448
|
-
end
|
353
|
+
private
|
449
354
|
|
450
|
-
def
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
355
|
+
def exec_stmt(sql, name, binds)
|
356
|
+
cache = {}
|
357
|
+
log(sql, name, binds) do
|
358
|
+
if binds.empty?
|
359
|
+
stmt = @connection.prepare(sql)
|
360
|
+
else
|
361
|
+
cache = @statements[sql] ||= {
|
362
|
+
:stmt => @connection.prepare(sql)
|
363
|
+
}
|
364
|
+
stmt = cache[:stmt]
|
459
365
|
end
|
460
366
|
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
result.each { |field| columns << MysqlColumn.new(field[0], field[4], field[1], field[2] == "YES") }
|
473
|
-
result.free
|
474
|
-
columns
|
475
|
-
end
|
476
|
-
|
477
|
-
def create_table(table_name, options = {}) #:nodoc:
|
478
|
-
super(table_name, options.reverse_merge(:options => "ENGINE=InnoDB"))
|
479
|
-
end
|
480
|
-
|
481
|
-
def rename_table(table_name, new_name)
|
482
|
-
execute "RENAME TABLE #{quote_table_name(table_name)} TO #{quote_table_name(new_name)}"
|
483
|
-
end
|
367
|
+
begin
|
368
|
+
stmt.execute(*binds.map { |col, val| type_cast(val, col) })
|
369
|
+
rescue Mysql::Error => e
|
370
|
+
# Older versions of MySQL leave the prepared statement in a bad
|
371
|
+
# place when an error occurs. To support older mysql versions, we
|
372
|
+
# need to close the statement and delete the statement from the
|
373
|
+
# cache.
|
374
|
+
stmt.close
|
375
|
+
@statements.delete sql
|
376
|
+
raise e
|
377
|
+
end
|
484
378
|
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
379
|
+
cols = nil
|
380
|
+
if metadata = stmt.result_metadata
|
381
|
+
cols = cache[:cols] ||= metadata.fetch_fields.map { |field|
|
382
|
+
field.name
|
383
|
+
}
|
384
|
+
end
|
491
385
|
|
492
|
-
|
493
|
-
|
494
|
-
change_column table_name, column_name, column.sql_type, :default => default
|
495
|
-
end
|
386
|
+
result_set = ActiveRecord::Result.new(cols, stmt.to_a) if cols
|
387
|
+
affected_rows = stmt.affected_rows
|
496
388
|
|
497
|
-
|
498
|
-
|
389
|
+
stmt.result_metadata.free if cols
|
390
|
+
stmt.free_result
|
391
|
+
stmt.close if binds.empty?
|
499
392
|
|
500
|
-
|
501
|
-
execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
|
393
|
+
[result_set, affected_rows]
|
502
394
|
end
|
503
|
-
|
504
|
-
change_column table_name, column_name, column.sql_type, :null => null
|
505
395
|
end
|
506
396
|
|
507
|
-
def
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
options[:default] = column.default
|
397
|
+
def connect
|
398
|
+
encoding = @config[:encoding]
|
399
|
+
if encoding
|
400
|
+
@connection.options(Mysql::SET_CHARSET_NAME, encoding) rescue nil
|
512
401
|
end
|
513
402
|
|
514
|
-
|
515
|
-
|
403
|
+
if @config[:sslca] || @config[:sslkey]
|
404
|
+
@connection.ssl_set(@config[:sslkey], @config[:sslcert], @config[:sslca], @config[:sslcapath], @config[:sslcipher])
|
516
405
|
end
|
517
406
|
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
execute(change_column_sql)
|
522
|
-
end
|
407
|
+
@connection.options(Mysql::OPT_CONNECT_TIMEOUT, @config[:connect_timeout]) if @config[:connect_timeout]
|
408
|
+
@connection.options(Mysql::OPT_READ_TIMEOUT, @config[:read_timeout]) if @config[:read_timeout]
|
409
|
+
@connection.options(Mysql::OPT_WRITE_TIMEOUT, @config[:write_timeout]) if @config[:write_timeout]
|
523
410
|
|
524
|
-
|
525
|
-
options = {}
|
526
|
-
if column = columns(table_name).find { |c| c.name == column_name.to_s }
|
527
|
-
options[:default] = column.default
|
528
|
-
options[:null] = column.null
|
529
|
-
else
|
530
|
-
raise ActiveRecordError, "No such column: #{table_name}.#{column_name}"
|
531
|
-
end
|
532
|
-
current_type = select_one("SHOW COLUMNS FROM #{quote_table_name(table_name)} LIKE '#{column_name}'")["Type"]
|
533
|
-
rename_column_sql = "ALTER TABLE #{quote_table_name(table_name)} CHANGE #{quote_column_name(column_name)} #{quote_column_name(new_column_name)} #{current_type}"
|
534
|
-
add_column_options!(rename_column_sql, options)
|
535
|
-
execute(rename_column_sql)
|
536
|
-
end
|
411
|
+
@connection.real_connect(*@connection_options)
|
537
412
|
|
538
|
-
|
539
|
-
|
540
|
-
return super unless type.to_s == 'integer'
|
541
|
-
|
542
|
-
case limit
|
543
|
-
when 1; 'tinyint'
|
544
|
-
when 2; 'smallint'
|
545
|
-
when 3; 'mediumint'
|
546
|
-
when nil, 4, 11; 'int(11)' # compatibility with MySQL default
|
547
|
-
when 5..8; 'bigint'
|
548
|
-
else raise(ActiveRecordError, "No integer type has byte size #{limit}")
|
549
|
-
end
|
550
|
-
end
|
413
|
+
# reconnect must be set after real_connect is called, because real_connect sets it to false internally
|
414
|
+
@connection.reconnect = !!@config[:reconnect] if @connection.respond_to?(:reconnect=)
|
551
415
|
|
552
|
-
|
553
|
-
if options[:first]
|
554
|
-
sql << " FIRST"
|
555
|
-
elsif options[:after]
|
556
|
-
sql << " AFTER #{quote_column_name(options[:after])}"
|
557
|
-
end
|
558
|
-
end
|
559
|
-
|
560
|
-
# SHOW VARIABLES LIKE 'name'
|
561
|
-
def show_variable(name)
|
562
|
-
variables = select_all("SHOW VARIABLES LIKE '#{name}'")
|
563
|
-
variables.first['Value'] unless variables.empty?
|
416
|
+
configure_connection
|
564
417
|
end
|
565
418
|
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
result = execute("describe #{quote_table_name(table)}")
|
570
|
-
result.each_hash do |h|
|
571
|
-
keys << h["Field"]if h["Key"] == "PRI"
|
572
|
-
end
|
573
|
-
result.free
|
574
|
-
keys.length == 1 ? [keys.first, nil] : nil
|
575
|
-
end
|
419
|
+
def configure_connection
|
420
|
+
encoding = @config[:encoding]
|
421
|
+
execute("SET NAMES '#{encoding}'", :skip_logging) if encoding
|
576
422
|
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
pk_and_sequence && pk_and_sequence.first
|
423
|
+
# By default, MySQL 'where id is null' selects the last inserted id.
|
424
|
+
# Turn this off. http://dev.rubyonrails.org/ticket/6778
|
425
|
+
execute("SET SQL_AUTO_IS_NULL=0", :skip_logging)
|
581
426
|
end
|
582
427
|
|
583
|
-
def
|
584
|
-
|
428
|
+
def select(sql, name = nil, binds = [])
|
429
|
+
@connection.query_with_result = true
|
430
|
+
rows = exec_query(sql, name, binds).to_a
|
431
|
+
@connection.more_results && @connection.next_result # invoking stored procedures with CLIENT_MULTI_RESULTS requires this to tidy up else connection will be dropped
|
432
|
+
rows
|
585
433
|
end
|
586
434
|
|
587
|
-
|
588
|
-
|
435
|
+
# Returns the version of the connected MySQL server.
|
436
|
+
def version
|
437
|
+
@version ||= @connection.server_info.scan(/^(\d+)\.(\d+)\.(\d+)/).flatten.map { |v| v.to_i }
|
589
438
|
end
|
590
|
-
|
591
|
-
protected
|
592
|
-
def quoted_columns_for_index(column_names, options = {})
|
593
|
-
length = options[:length] if options.is_a?(Hash)
|
594
|
-
|
595
|
-
quoted_column_names = case length
|
596
|
-
when Hash
|
597
|
-
column_names.map {|name| length[name] ? "#{quote_column_name(name)}(#{length[name]})" : quote_column_name(name) }
|
598
|
-
when Fixnum
|
599
|
-
column_names.map {|name| "#{quote_column_name(name)}(#{length})"}
|
600
|
-
else
|
601
|
-
column_names.map {|name| quote_column_name(name) }
|
602
|
-
end
|
603
|
-
end
|
604
|
-
|
605
|
-
private
|
606
|
-
def connect
|
607
|
-
encoding = @config[:encoding]
|
608
|
-
if encoding
|
609
|
-
@connection.options(Mysql::SET_CHARSET_NAME, encoding) rescue nil
|
610
|
-
end
|
611
|
-
|
612
|
-
if @config[:sslca] || @config[:sslkey]
|
613
|
-
@connection.ssl_set(@config[:sslkey], @config[:sslcert], @config[:sslca], @config[:sslcapath], @config[:sslcipher])
|
614
|
-
end
|
615
|
-
|
616
|
-
@connection.options(Mysql::OPT_CONNECT_TIMEOUT, @config[:connect_timeout]) if @config[:connect_timeout]
|
617
|
-
@connection.options(Mysql::OPT_READ_TIMEOUT, @config[:read_timeout]) if @config[:read_timeout]
|
618
|
-
@connection.options(Mysql::OPT_WRITE_TIMEOUT, @config[:write_timeout]) if @config[:write_timeout]
|
619
|
-
|
620
|
-
@connection.real_connect(*@connection_options)
|
621
|
-
|
622
|
-
# reconnect must be set after real_connect is called, because real_connect sets it to false internally
|
623
|
-
@connection.reconnect = !!@config[:reconnect] if @connection.respond_to?(:reconnect=)
|
624
|
-
|
625
|
-
configure_connection
|
626
|
-
end
|
627
|
-
|
628
|
-
def configure_connection
|
629
|
-
encoding = @config[:encoding]
|
630
|
-
execute("SET NAMES '#{encoding}'") if encoding
|
631
|
-
|
632
|
-
# By default, MySQL 'where id is null' selects the last inserted id.
|
633
|
-
# Turn this off. http://dev.rubyonrails.org/ticket/6778
|
634
|
-
execute("SET SQL_AUTO_IS_NULL=0")
|
635
|
-
end
|
636
|
-
|
637
|
-
def select(sql, name = nil)
|
638
|
-
@connection.query_with_result = true
|
639
|
-
result = execute(sql, name)
|
640
|
-
rows = result.all_hashes
|
641
|
-
result.free
|
642
|
-
@connection.more_results && @connection.next_result # invoking stored procedures with CLIENT_MULTI_RESULTS requires this to tidy up else connection will be dropped
|
643
|
-
rows
|
644
|
-
end
|
645
|
-
|
646
|
-
def supports_views?
|
647
|
-
version[0] >= 5
|
648
|
-
end
|
649
|
-
|
650
|
-
def version
|
651
|
-
@version ||= @connection.server_info.scan(/^(\d+)\.(\d+)\.(\d+)/).flatten.map { |v| v.to_i }
|
652
|
-
end
|
653
|
-
|
654
|
-
def column_for(table_name, column_name)
|
655
|
-
unless column = columns(table_name).find { |c| c.name == column_name.to_s }
|
656
|
-
raise "No such column: #{table_name}.#{column_name}"
|
657
|
-
end
|
658
|
-
column
|
659
|
-
end
|
660
439
|
end
|
661
440
|
end
|
662
441
|
end
|