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,83 +1,23 @@
|
|
1
|
-
# encoding: binary
|
2
1
|
require 'active_record/connection_adapters/abstract_adapter'
|
2
|
+
require 'active_record/connection_adapters/statement_pool'
|
3
|
+
require 'active_support/core_ext/string/encoding'
|
4
|
+
require 'arel/visitors/bind_visitor'
|
3
5
|
|
4
6
|
module ActiveRecord
|
5
|
-
class Base
|
6
|
-
class << self
|
7
|
-
# Establishes a connection to the database that's used by all Active Record objects
|
8
|
-
def sqlite_connection(config) # :nodoc:
|
9
|
-
parse_sqlite_config!(config)
|
10
|
-
|
11
|
-
unless self.class.const_defined?(:SQLite)
|
12
|
-
require_library_or_gem(config[:adapter])
|
13
|
-
|
14
|
-
db = SQLite::Database.new(config[:database], 0)
|
15
|
-
db.show_datatypes = "ON" if !defined? SQLite::Version
|
16
|
-
db.results_as_hash = true if defined? SQLite::Version
|
17
|
-
db.type_translation = false
|
18
|
-
|
19
|
-
message = "Support for SQLite2Adapter and DeprecatedSQLiteAdapter has been removed from Rails 3. "
|
20
|
-
message << "You should migrate to SQLite 3+ or use the plugin from git://github.com/rails/sqlite2_adapter.git with Rails 3."
|
21
|
-
ActiveSupport::Deprecation.warn(message)
|
22
|
-
|
23
|
-
# "Downgrade" deprecated sqlite API
|
24
|
-
if SQLite.const_defined?(:Version)
|
25
|
-
ConnectionAdapters::SQLite2Adapter.new(db, logger, config)
|
26
|
-
else
|
27
|
-
ConnectionAdapters::DeprecatedSQLiteAdapter.new(db, logger, config)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
def parse_sqlite_config!(config)
|
34
|
-
if config.include?(:dbfile)
|
35
|
-
ActiveSupport::Deprecation.warn "Please update config/database.yml to use 'database' instead of 'dbfile'"
|
36
|
-
end
|
37
|
-
|
38
|
-
config[:database] ||= config[:dbfile]
|
39
|
-
# Require database.
|
40
|
-
unless config[:database]
|
41
|
-
raise ArgumentError, "No database file specified. Missing argument: database"
|
42
|
-
end
|
43
|
-
|
44
|
-
# Allow database path relative to RAILS_ROOT, but only if
|
45
|
-
# the database path is not the special path that tells
|
46
|
-
# Sqlite to build a database only in memory.
|
47
|
-
if Object.const_defined?(:RAILS_ROOT) && ':memory:' != config[:database]
|
48
|
-
config[:database] = File.expand_path(config[:database], RAILS_ROOT)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
7
|
module ConnectionAdapters #:nodoc:
|
55
8
|
class SQLiteColumn < Column #:nodoc:
|
56
9
|
class << self
|
57
|
-
def string_to_binary(value)
|
58
|
-
value = value.dup.force_encoding(Encoding::BINARY) if value.respond_to?(:force_encoding)
|
59
|
-
value.gsub(/\0|\%/n) do |b|
|
60
|
-
case b
|
61
|
-
when "\0" then "%00"
|
62
|
-
when "%" then "%25"
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
10
|
def binary_to_string(value)
|
68
|
-
|
69
|
-
|
70
|
-
case b
|
71
|
-
when "%00" then "\0"
|
72
|
-
when "%25" then "%"
|
73
|
-
end
|
11
|
+
if value.respond_to?(:force_encoding) && value.encoding != Encoding::ASCII_8BIT
|
12
|
+
value = value.force_encoding(Encoding::ASCII_8BIT)
|
74
13
|
end
|
14
|
+
value
|
75
15
|
end
|
76
16
|
end
|
77
17
|
end
|
78
18
|
|
79
|
-
# The SQLite adapter works with both the 2.x and 3.x series of SQLite with the sqlite-ruby
|
80
|
-
# from http://rubyforge.org/projects/sqlite-ruby/).
|
19
|
+
# The SQLite adapter works with both the 2.x and 3.x series of SQLite with the sqlite-ruby
|
20
|
+
# drivers (available both as gems and from http://rubyforge.org/projects/sqlite-ruby/).
|
81
21
|
#
|
82
22
|
# Options:
|
83
23
|
#
|
@@ -87,56 +27,137 @@ module ActiveRecord
|
|
87
27
|
include Comparable
|
88
28
|
|
89
29
|
def initialize(version_string)
|
90
|
-
@version = version_string.split('.').map
|
30
|
+
@version = version_string.split('.').map { |v| v.to_i }
|
91
31
|
end
|
92
32
|
|
93
33
|
def <=>(version_string)
|
94
|
-
@version <=> version_string.split('.').map
|
34
|
+
@version <=> version_string.split('.').map { |v| v.to_i }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class StatementPool < ConnectionAdapters::StatementPool
|
39
|
+
def initialize(connection, max)
|
40
|
+
super
|
41
|
+
@cache = Hash.new { |h,pid| h[pid] = {} }
|
42
|
+
end
|
43
|
+
|
44
|
+
def each(&block); cache.each(&block); end
|
45
|
+
def key?(key); cache.key?(key); end
|
46
|
+
def [](key); cache[key]; end
|
47
|
+
def length; cache.length; end
|
48
|
+
|
49
|
+
def []=(sql, key)
|
50
|
+
while @max <= cache.size
|
51
|
+
dealloc(cache.shift.last[:stmt])
|
52
|
+
end
|
53
|
+
cache[sql] = key
|
54
|
+
end
|
55
|
+
|
56
|
+
def clear
|
57
|
+
cache.values.each do |hash|
|
58
|
+
dealloc hash[:stmt]
|
59
|
+
end
|
60
|
+
cache.clear
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
def cache
|
65
|
+
@cache[$$]
|
95
66
|
end
|
67
|
+
|
68
|
+
def dealloc(stmt)
|
69
|
+
stmt.close unless stmt.closed?
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class BindSubstitution < Arel::Visitors::SQLite # :nodoc:
|
74
|
+
include Arel::Visitors::BindVisitor
|
96
75
|
end
|
97
76
|
|
98
77
|
def initialize(connection, logger, config)
|
99
78
|
super(connection, logger)
|
79
|
+
@statements = StatementPool.new(@connection,
|
80
|
+
config.fetch(:statement_limit) { 1000 })
|
100
81
|
@config = config
|
82
|
+
|
83
|
+
if config.fetch(:prepared_statements) { true }
|
84
|
+
@visitor = Arel::Visitors::SQLite.new self
|
85
|
+
else
|
86
|
+
@visitor = BindSubstitution.new self
|
87
|
+
end
|
101
88
|
end
|
102
89
|
|
103
90
|
def adapter_name #:nodoc:
|
104
91
|
'SQLite'
|
105
92
|
end
|
106
93
|
|
94
|
+
# Returns true if SQLite version is '2.0.0' or greater, false otherwise.
|
107
95
|
def supports_ddl_transactions?
|
108
96
|
sqlite_version >= '2.0.0'
|
109
97
|
end
|
110
98
|
|
99
|
+
# Returns true if SQLite version is '3.6.8' or greater, false otherwise.
|
100
|
+
def supports_savepoints?
|
101
|
+
sqlite_version >= '3.6.8'
|
102
|
+
end
|
103
|
+
|
104
|
+
# Returns true, since this connection adapter supports prepared statement
|
105
|
+
# caching.
|
106
|
+
def supports_statement_cache?
|
107
|
+
true
|
108
|
+
end
|
109
|
+
|
110
|
+
# Returns true, since this connection adapter supports migrations.
|
111
111
|
def supports_migrations? #:nodoc:
|
112
112
|
true
|
113
113
|
end
|
114
114
|
|
115
|
+
# Returns true.
|
115
116
|
def supports_primary_key? #:nodoc:
|
116
117
|
true
|
117
118
|
end
|
118
119
|
|
120
|
+
# Returns true.
|
121
|
+
def supports_explain?
|
122
|
+
true
|
123
|
+
end
|
124
|
+
|
119
125
|
def requires_reloading?
|
120
126
|
true
|
121
127
|
end
|
122
128
|
|
129
|
+
# Returns true if SQLite version is '3.1.6' or greater, false otherwise.
|
123
130
|
def supports_add_column?
|
124
131
|
sqlite_version >= '3.1.6'
|
125
132
|
end
|
126
|
-
|
133
|
+
|
134
|
+
# Disconnects from the database if already connected. Otherwise, this
|
135
|
+
# method does nothing.
|
127
136
|
def disconnect!
|
128
137
|
super
|
138
|
+
clear_cache!
|
129
139
|
@connection.close rescue nil
|
130
140
|
end
|
131
141
|
|
142
|
+
# Clears the prepared statements cache.
|
143
|
+
def clear_cache!
|
144
|
+
@statements.clear
|
145
|
+
end
|
146
|
+
|
147
|
+
# Returns true if SQLite version is '3.2.6' or greater, false otherwise.
|
132
148
|
def supports_count_distinct? #:nodoc:
|
133
149
|
sqlite_version >= '3.2.6'
|
134
150
|
end
|
135
151
|
|
152
|
+
# Returns true if SQLite version is '3.1.0' or greater, false otherwise.
|
136
153
|
def supports_autoincrement? #:nodoc:
|
137
154
|
sqlite_version >= '3.1.0'
|
138
155
|
end
|
139
156
|
|
157
|
+
def supports_index_sort_order?
|
158
|
+
sqlite_version >= '3.3.0'
|
159
|
+
end
|
160
|
+
|
140
161
|
def native_database_types #:nodoc:
|
141
162
|
{
|
142
163
|
:primary_key => default_primary_key_type,
|
@@ -165,11 +186,96 @@ module ActiveRecord
|
|
165
186
|
%Q("#{name.to_s.gsub('"', '""')}")
|
166
187
|
end
|
167
188
|
|
189
|
+
# Quote date/time values for use in SQL input. Includes microseconds
|
190
|
+
# if the value is a Time responding to usec.
|
191
|
+
def quoted_date(value) #:nodoc:
|
192
|
+
if value.respond_to?(:usec)
|
193
|
+
"#{super}.#{sprintf("%06d", value.usec)}"
|
194
|
+
else
|
195
|
+
super
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
if "<3".encoding_aware?
|
200
|
+
def type_cast(value, column) # :nodoc:
|
201
|
+
return value.to_f if BigDecimal === value
|
202
|
+
return super unless String === value
|
203
|
+
return super unless column && value
|
204
|
+
|
205
|
+
value = super
|
206
|
+
if column.type == :string && value.encoding == Encoding::ASCII_8BIT
|
207
|
+
logger.error "Binary data inserted for `string` type on column `#{column.name}`" if logger
|
208
|
+
value = value.encode Encoding::UTF_8
|
209
|
+
end
|
210
|
+
value
|
211
|
+
end
|
212
|
+
else
|
213
|
+
def type_cast(value, column) # :nodoc:
|
214
|
+
return super unless BigDecimal === value
|
215
|
+
|
216
|
+
value.to_f
|
217
|
+
end
|
218
|
+
end
|
168
219
|
|
169
220
|
# DATABASE STATEMENTS ======================================
|
170
221
|
|
222
|
+
def explain(arel, binds = [])
|
223
|
+
sql = "EXPLAIN QUERY PLAN #{to_sql(arel, binds)}"
|
224
|
+
ExplainPrettyPrinter.new.pp(exec_query(sql, 'EXPLAIN', binds))
|
225
|
+
end
|
226
|
+
|
227
|
+
class ExplainPrettyPrinter
|
228
|
+
# Pretty prints the result of a EXPLAIN QUERY PLAN in a way that resembles
|
229
|
+
# the output of the SQLite shell:
|
230
|
+
#
|
231
|
+
# 0|0|0|SEARCH TABLE users USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)
|
232
|
+
# 0|1|1|SCAN TABLE posts (~100000 rows)
|
233
|
+
#
|
234
|
+
def pp(result) # :nodoc:
|
235
|
+
result.rows.map do |row|
|
236
|
+
row.join('|')
|
237
|
+
end.join("\n") + "\n"
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
def exec_query(sql, name = nil, binds = [])
|
242
|
+
log(sql, name, binds) do
|
243
|
+
|
244
|
+
# Don't cache statements without bind values
|
245
|
+
if binds.empty?
|
246
|
+
stmt = @connection.prepare(sql)
|
247
|
+
cols = stmt.columns
|
248
|
+
records = stmt.to_a
|
249
|
+
stmt.close
|
250
|
+
stmt = records
|
251
|
+
else
|
252
|
+
cache = @statements[sql] ||= {
|
253
|
+
:stmt => @connection.prepare(sql)
|
254
|
+
}
|
255
|
+
stmt = cache[:stmt]
|
256
|
+
cols = cache[:cols] ||= stmt.columns
|
257
|
+
stmt.reset!
|
258
|
+
stmt.bind_params binds.map { |col, val|
|
259
|
+
type_cast(val, col)
|
260
|
+
}
|
261
|
+
end
|
262
|
+
|
263
|
+
ActiveRecord::Result.new(cols, stmt.to_a)
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def exec_delete(sql, name = 'SQL', binds = [])
|
268
|
+
exec_query(sql, name, binds)
|
269
|
+
@connection.changes
|
270
|
+
end
|
271
|
+
alias :exec_update :exec_delete
|
272
|
+
|
273
|
+
def last_inserted_id(result)
|
274
|
+
@connection.last_insert_row_id
|
275
|
+
end
|
276
|
+
|
171
277
|
def execute(sql, name = nil) #:nodoc:
|
172
|
-
|
278
|
+
log(sql, name) { @connection.execute(sql) }
|
173
279
|
end
|
174
280
|
|
175
281
|
def update_sql(sql, name = nil) #:nodoc:
|
@@ -183,73 +289,104 @@ module ActiveRecord
|
|
183
289
|
end
|
184
290
|
|
185
291
|
def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
|
186
|
-
super
|
292
|
+
super
|
293
|
+
id_value || @connection.last_insert_row_id
|
187
294
|
end
|
295
|
+
alias :create :insert_sql
|
188
296
|
|
189
297
|
def select_rows(sql, name = nil)
|
190
|
-
|
191
|
-
(0...(row.size / 2)).map { |i| row[i] }
|
192
|
-
end
|
298
|
+
exec_query(sql, name).rows
|
193
299
|
end
|
194
300
|
|
195
|
-
def
|
196
|
-
|
301
|
+
def create_savepoint
|
302
|
+
execute("SAVEPOINT #{current_savepoint_name}")
|
197
303
|
end
|
198
304
|
|
199
|
-
def
|
200
|
-
|
305
|
+
def rollback_to_savepoint
|
306
|
+
execute("ROLLBACK TO SAVEPOINT #{current_savepoint_name}")
|
201
307
|
end
|
202
308
|
|
203
|
-
def
|
204
|
-
|
309
|
+
def release_savepoint
|
310
|
+
execute("RELEASE SAVEPOINT #{current_savepoint_name}")
|
311
|
+
end
|
312
|
+
|
313
|
+
def begin_db_transaction #:nodoc:
|
314
|
+
log('begin transaction',nil) { @connection.transaction }
|
205
315
|
end
|
206
316
|
|
207
|
-
|
208
|
-
|
209
|
-
sql
|
317
|
+
def commit_db_transaction #:nodoc:
|
318
|
+
log('commit transaction',nil) { @connection.commit }
|
210
319
|
end
|
211
320
|
|
321
|
+
def rollback_db_transaction #:nodoc:
|
322
|
+
log('rollback transaction',nil) { @connection.rollback }
|
323
|
+
end
|
212
324
|
|
213
325
|
# SCHEMA STATEMENTS ========================================
|
214
326
|
|
215
|
-
def tables(name = nil) #:nodoc:
|
327
|
+
def tables(name = 'SCHEMA', table_name = nil) #:nodoc:
|
216
328
|
sql = <<-SQL
|
217
329
|
SELECT name
|
218
330
|
FROM sqlite_master
|
219
331
|
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
|
220
332
|
SQL
|
333
|
+
sql << " AND name = #{quote_table_name(table_name)}" if table_name
|
221
334
|
|
222
|
-
|
335
|
+
exec_query(sql, name).map do |row|
|
223
336
|
row['name']
|
224
337
|
end
|
225
338
|
end
|
226
339
|
|
340
|
+
def table_exists?(name)
|
341
|
+
name && tables('SCHEMA', name).any?
|
342
|
+
end
|
343
|
+
|
344
|
+
# Returns an array of +SQLiteColumn+ objects for the table specified by +table_name+.
|
227
345
|
def columns(table_name, name = nil) #:nodoc:
|
228
346
|
table_structure(table_name).map do |field|
|
347
|
+
case field["dflt_value"]
|
348
|
+
when /^null$/i
|
349
|
+
field["dflt_value"] = nil
|
350
|
+
when /^'(.*)'$/
|
351
|
+
field["dflt_value"] = $1.gsub(/''/, "'")
|
352
|
+
when /^"(.*)"$/
|
353
|
+
field["dflt_value"] = $1.gsub(/""/, '"')
|
354
|
+
end
|
355
|
+
|
229
356
|
SQLiteColumn.new(field['name'], field['dflt_value'], field['type'], field['notnull'].to_i == 0)
|
230
357
|
end
|
231
358
|
end
|
232
359
|
|
360
|
+
# Returns an array of indexes for the given table.
|
233
361
|
def indexes(table_name, name = nil) #:nodoc:
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
362
|
+
exec_query("PRAGMA index_list(#{quote_table_name(table_name)})", 'SCHEMA').map do |row|
|
363
|
+
IndexDefinition.new(
|
364
|
+
table_name,
|
365
|
+
row['name'],
|
366
|
+
row['unique'] != 0,
|
367
|
+
exec_query("PRAGMA index_info('#{row['name']}')", 'SCHEMA').map { |col|
|
368
|
+
col['name']
|
369
|
+
})
|
239
370
|
end
|
240
371
|
end
|
241
372
|
|
242
373
|
def primary_key(table_name) #:nodoc:
|
243
|
-
column = table_structure(table_name).find {|field|
|
244
|
-
|
374
|
+
column = table_structure(table_name).find { |field|
|
375
|
+
field['pk'] == 1
|
376
|
+
}
|
377
|
+
column && column['name']
|
245
378
|
end
|
246
379
|
|
247
380
|
def remove_index!(table_name, index_name) #:nodoc:
|
248
|
-
|
381
|
+
exec_query "DROP INDEX #{quote_column_name(index_name)}"
|
249
382
|
end
|
250
383
|
|
384
|
+
# Renames a table.
|
385
|
+
#
|
386
|
+
# Example:
|
387
|
+
# rename_table('octopuses', 'octopi')
|
251
388
|
def rename_table(name, new_name)
|
252
|
-
|
389
|
+
exec_query "ALTER TABLE #{quote_table_name(name)} RENAME TO #{quote_table_name(new_name)}"
|
253
390
|
end
|
254
391
|
|
255
392
|
# See: http://www.sqlite.org/lang_altertable.html
|
@@ -269,8 +406,15 @@ module ActiveRecord
|
|
269
406
|
end
|
270
407
|
|
271
408
|
def remove_column(table_name, *column_names) #:nodoc:
|
272
|
-
raise ArgumentError.new("You must specify at least one column name.
|
273
|
-
|
409
|
+
raise ArgumentError.new("You must specify at least one column name. Example: remove_column(:people, :first_name)") if column_names.empty?
|
410
|
+
|
411
|
+
if column_names.flatten!
|
412
|
+
message = 'Passing array to remove_columns is deprecated, please use ' +
|
413
|
+
'multiple arguments, like: `remove_columns(:posts, :foo, :bar)`'
|
414
|
+
ActiveSupport::Deprecation.warn message, caller
|
415
|
+
end
|
416
|
+
|
417
|
+
column_names.each do |column_name|
|
274
418
|
alter_table(table_name) do |definition|
|
275
419
|
definition.columns.delete(definition[column_name])
|
276
420
|
end
|
@@ -286,7 +430,7 @@ module ActiveRecord
|
|
286
430
|
|
287
431
|
def change_column_null(table_name, column_name, null, default = nil)
|
288
432
|
unless null || default.nil?
|
289
|
-
|
433
|
+
exec_query("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
|
290
434
|
end
|
291
435
|
alter_table(table_name) do |definition|
|
292
436
|
definition[column_name].null = null
|
@@ -301,6 +445,8 @@ module ActiveRecord
|
|
301
445
|
self.limit = options[:limit] if options.include?(:limit)
|
302
446
|
self.default = options[:default] if include_default
|
303
447
|
self.null = options[:null] if options.include?(:null)
|
448
|
+
self.precision = options[:precision] if options.include?(:precision)
|
449
|
+
self.scale = options[:scale] if options.include?(:scale)
|
304
450
|
end
|
305
451
|
end
|
306
452
|
end
|
@@ -312,27 +458,19 @@ module ActiveRecord
|
|
312
458
|
alter_table(table_name, :rename => {column_name.to_s => new_column_name.to_s})
|
313
459
|
end
|
314
460
|
|
315
|
-
def
|
316
|
-
"
|
461
|
+
def empty_insert_statement_value
|
462
|
+
"VALUES(NULL)"
|
317
463
|
end
|
318
464
|
|
319
465
|
protected
|
320
|
-
def select(sql, name = nil) #:nodoc:
|
321
|
-
|
322
|
-
record = {}
|
323
|
-
row.each_key do |key|
|
324
|
-
if key.is_a?(String)
|
325
|
-
record[key.sub(/^"?\w+"?\./, '')] = row[key]
|
326
|
-
end
|
327
|
-
end
|
328
|
-
record
|
329
|
-
end
|
466
|
+
def select(sql, name = nil, binds = []) #:nodoc:
|
467
|
+
exec_query(sql, name, binds).to_a
|
330
468
|
end
|
331
469
|
|
332
470
|
def table_structure(table_name)
|
333
|
-
|
334
|
-
|
335
|
-
|
471
|
+
structure = exec_query("PRAGMA table_info(#{quote_table_name(table_name)})", 'SCHEMA').to_hash
|
472
|
+
raise(ActiveRecord::StatementInvalid, "Could not find table '#{table_name}'") if structure.empty?
|
473
|
+
structure
|
336
474
|
end
|
337
475
|
|
338
476
|
def alter_table(table_name, options = {}) #:nodoc:
|
@@ -352,7 +490,11 @@ module ActiveRecord
|
|
352
490
|
end
|
353
491
|
|
354
492
|
def copy_table(from, to, options = {}) #:nodoc:
|
355
|
-
|
493
|
+
from_primary_key = primary_key(from)
|
494
|
+
options[:primary_key] = from_primary_key if from_primary_key != 'id'
|
495
|
+
unless options[:primary_key]
|
496
|
+
options[:id] = !columns(from).detect{|c| c.name == 'id'}.nil? && 'id' == from_primary_key
|
497
|
+
end
|
356
498
|
create_table(to, options) do |definition|
|
357
499
|
@definition = definition
|
358
500
|
columns(from).each do |column|
|
@@ -360,12 +502,13 @@ module ActiveRecord
|
|
360
502
|
(options[:rename][column.name] ||
|
361
503
|
options[:rename][column.name.to_sym] ||
|
362
504
|
column.name) : column.name
|
363
|
-
|
505
|
+
|
364
506
|
@definition.column(column_name, column.type,
|
365
507
|
:limit => column.limit, :default => column.default,
|
508
|
+
:precision => column.precision, :scale => column.scale,
|
366
509
|
:null => column.null)
|
367
510
|
end
|
368
|
-
@definition.primary_key(
|
511
|
+
@definition.primary_key(from_primary_key) if from_primary_key
|
369
512
|
yield @definition if block_given?
|
370
513
|
end
|
371
514
|
|
@@ -384,14 +527,14 @@ module ActiveRecord
|
|
384
527
|
name = name[5..-1]
|
385
528
|
end
|
386
529
|
|
387
|
-
to_column_names = columns(to).map
|
530
|
+
to_column_names = columns(to).map { |c| c.name }
|
388
531
|
columns = index.columns.map {|c| rename[c] || c }.select do |column|
|
389
532
|
to_column_names.include?(column)
|
390
533
|
end
|
391
534
|
|
392
535
|
unless columns.empty?
|
393
536
|
# index name can't be the same
|
394
|
-
opts = { :name => name.gsub(/_(#{from})_/, "
|
537
|
+
opts = { :name => name.gsub(/(^|_)(#{from})_/, "\\1#{to}_") }
|
395
538
|
opts[:unique] = true if index.unique
|
396
539
|
add_index(to, columns, opts)
|
397
540
|
end
|
@@ -399,29 +542,18 @@ module ActiveRecord
|
|
399
542
|
end
|
400
543
|
|
401
544
|
def copy_table_contents(from, to, columns, rename = {}) #:nodoc:
|
402
|
-
column_mappings = Hash[
|
403
|
-
rename.
|
545
|
+
column_mappings = Hash[columns.map {|name| [name, name]}]
|
546
|
+
rename.each { |a| column_mappings[a.last] = a.first }
|
404
547
|
from_columns = columns(from).collect {|col| col.name}
|
405
548
|
columns = columns.find_all{|col| from_columns.include?(column_mappings[col])}
|
406
549
|
quoted_columns = columns.map { |col| quote_column_name(col) } * ','
|
407
550
|
|
408
551
|
quoted_to = quote_table_name(to)
|
409
|
-
|
552
|
+
exec_query("SELECT * FROM #{quote_table_name(from)}").each do |row|
|
410
553
|
sql = "INSERT INTO #{quoted_to} (#{quoted_columns}) VALUES ("
|
411
554
|
sql << columns.map {|col| quote row[column_mappings[col]]} * ', '
|
412
555
|
sql << ')'
|
413
|
-
|
414
|
-
end
|
415
|
-
end
|
416
|
-
|
417
|
-
def catch_schema_changes
|
418
|
-
return yield
|
419
|
-
rescue ActiveRecord::StatementInvalid => exception
|
420
|
-
if exception.message =~ /database schema has changed/
|
421
|
-
reconnect!
|
422
|
-
retry
|
423
|
-
else
|
424
|
-
raise
|
556
|
+
exec_query sql
|
425
557
|
end
|
426
558
|
end
|
427
559
|
|
@@ -431,24 +563,21 @@ module ActiveRecord
|
|
431
563
|
|
432
564
|
def default_primary_key_type
|
433
565
|
if supports_autoincrement?
|
434
|
-
'INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL'
|
566
|
+
'INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL'
|
435
567
|
else
|
436
|
-
'INTEGER PRIMARY KEY NOT NULL'
|
568
|
+
'INTEGER PRIMARY KEY NOT NULL'
|
437
569
|
end
|
438
570
|
end
|
439
|
-
end
|
440
571
|
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
572
|
+
def translate_exception(exception, message)
|
573
|
+
case exception.message
|
574
|
+
when /column(s)? .* (is|are) not unique/
|
575
|
+
RecordNotUnique.new(message, exception)
|
576
|
+
else
|
577
|
+
super
|
578
|
+
end
|
579
|
+
end
|
446
580
|
|
447
|
-
class DeprecatedSQLiteAdapter < SQLite2Adapter # :nodoc:
|
448
|
-
def insert(sql, name = nil, pk = nil, id_value = nil)
|
449
|
-
execute(sql, name = nil)
|
450
|
-
id_value || @connection.last_insert_rowid
|
451
|
-
end
|
452
581
|
end
|
453
582
|
end
|
454
583
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
class StatementPool
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
def initialize(connection, max = 1000)
|
7
|
+
@connection = connection
|
8
|
+
@max = max
|
9
|
+
end
|
10
|
+
|
11
|
+
def each
|
12
|
+
raise NotImplementedError
|
13
|
+
end
|
14
|
+
|
15
|
+
def key?(key)
|
16
|
+
raise NotImplementedError
|
17
|
+
end
|
18
|
+
|
19
|
+
def [](key)
|
20
|
+
raise NotImplementedError
|
21
|
+
end
|
22
|
+
|
23
|
+
def length
|
24
|
+
raise NotImplementedError
|
25
|
+
end
|
26
|
+
|
27
|
+
def []=(sql, key)
|
28
|
+
raise NotImplementedError
|
29
|
+
end
|
30
|
+
|
31
|
+
def clear
|
32
|
+
raise NotImplementedError
|
33
|
+
end
|
34
|
+
|
35
|
+
def delete(key)
|
36
|
+
raise NotImplementedError
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|