activerecord 2.3.18 → 3.0.0.beta
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.
- data/CHANGELOG +105 -34
- data/examples/performance.rb +3 -39
- data/examples/simple.rb +14 -0
- data/lib/active_record.rb +81 -47
- data/lib/active_record/aggregations.rb +1 -3
- data/lib/active_record/association_preload.rb +39 -54
- data/lib/active_record/associations.rb +262 -419
- data/lib/active_record/associations/association_collection.rb +85 -100
- data/lib/active_record/associations/association_proxy.rb +20 -18
- data/lib/active_record/associations/belongs_to_association.rb +8 -8
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +13 -35
- data/lib/active_record/associations/has_many_association.rb +11 -19
- data/lib/active_record/associations/has_many_through_association.rb +30 -183
- data/lib/active_record/associations/has_one_association.rb +10 -10
- data/lib/active_record/associations/has_one_through_association.rb +13 -11
- data/lib/active_record/associations/through_association_scope.rb +153 -0
- data/lib/active_record/attribute_methods.rb +17 -370
- data/lib/active_record/attribute_methods/before_type_cast.rb +33 -0
- data/lib/active_record/attribute_methods/dirty.rb +87 -0
- data/lib/active_record/attribute_methods/primary_key.rb +44 -0
- data/lib/active_record/attribute_methods/query.rb +37 -0
- data/lib/active_record/attribute_methods/read.rb +116 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +60 -0
- data/lib/active_record/attribute_methods/write.rb +37 -0
- data/lib/active_record/autosave_association.rb +20 -41
- data/lib/active_record/base.rb +357 -1180
- data/lib/active_record/batches.rb +10 -16
- data/lib/active_record/callbacks.rb +66 -126
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +17 -13
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +5 -25
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +4 -43
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +18 -72
- data/lib/active_record/connection_adapters/abstract_adapter.rb +16 -49
- data/lib/active_record/connection_adapters/mysql_adapter.rb +15 -27
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +84 -46
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +9 -3
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +34 -65
- data/lib/active_record/fixtures.rb +21 -25
- data/lib/active_record/locale/en.yml +9 -27
- data/lib/active_record/locking/optimistic.rb +16 -48
- data/lib/active_record/migration.rb +59 -46
- data/lib/active_record/named_scope.rb +85 -92
- data/lib/active_record/nested_attributes.rb +18 -24
- data/lib/active_record/observer.rb +18 -94
- data/lib/active_record/railtie.rb +83 -0
- data/lib/active_record/railties/controller_runtime.rb +38 -0
- data/lib/active_record/railties/databases.rake +477 -0
- data/lib/active_record/railties/subscriber.rb +27 -0
- data/lib/active_record/reflection.rb +2 -15
- data/lib/active_record/relation.rb +339 -0
- data/lib/active_record/relation/calculations.rb +259 -0
- data/lib/active_record/relation/finder_methods.rb +315 -0
- data/lib/active_record/relation/predicate_builder.rb +46 -0
- data/lib/active_record/relation/query_methods.rb +218 -0
- data/lib/active_record/relation/spawn_methods.rb +102 -0
- data/lib/active_record/schema_dumper.rb +10 -6
- data/lib/active_record/serialization.rb +31 -74
- data/lib/active_record/serializers/xml_serializer.rb +33 -121
- data/lib/active_record/session_store.rb +1 -9
- data/lib/active_record/test_case.rb +1 -3
- data/lib/active_record/timestamp.rb +7 -5
- data/lib/active_record/transactions.rb +9 -9
- data/lib/active_record/validations.rb +51 -1100
- data/lib/active_record/validations/associated.rb +47 -0
- data/lib/active_record/validations/uniqueness.rb +181 -0
- data/lib/active_record/version.rb +3 -3
- data/lib/generators/active_record.rb +30 -0
- data/lib/generators/active_record/migration/migration_generator.rb +25 -0
- data/lib/generators/active_record/migration/templates/migration.rb +11 -0
- data/lib/generators/active_record/model/model_generator.rb +33 -0
- data/lib/generators/active_record/model/templates/migration.rb +16 -0
- data/lib/generators/active_record/model/templates/model.rb +5 -0
- data/lib/generators/active_record/observer/observer_generator.rb +15 -0
- data/lib/generators/active_record/observer/templates/observer.rb +2 -0
- data/lib/generators/active_record/session_migration/session_migration_generator.rb +24 -0
- data/lib/generators/active_record/session_migration/templates/migration.rb +16 -0
- metadata +67 -325
- data/RUNNING_UNIT_TESTS +0 -36
- data/Rakefile +0 -268
- data/install.rb +0 -30
- data/lib/active_record/calculations.rb +0 -321
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +0 -57
- data/lib/active_record/dirty.rb +0 -183
- 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.yml +0 -14
- data/test/fixtures/categories/special_categories.yml +0 -9
- data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +0 -4
- 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,4 +1,5 @@
|
|
1
1
|
require 'active_record/connection_adapters/abstract_adapter'
|
2
|
+
require 'active_support/core_ext/kernel/requires'
|
2
3
|
|
3
4
|
begin
|
4
5
|
require_library_or_gem 'pg'
|
@@ -261,12 +262,20 @@ module ActiveRecord
|
|
261
262
|
true
|
262
263
|
end
|
263
264
|
|
264
|
-
#
|
265
|
-
def
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
265
|
+
# Does PostgreSQL support standard conforming strings?
|
266
|
+
def supports_standard_conforming_strings?
|
267
|
+
# Temporarily set the client message level above error to prevent unintentional
|
268
|
+
# error messages in the logs when working on a PostgreSQL database server that
|
269
|
+
# does not support standard conforming strings.
|
270
|
+
client_min_messages_old = client_min_messages
|
271
|
+
self.client_min_messages = 'panic'
|
272
|
+
|
273
|
+
# postgres-pr does not raise an exception when client_min_messages is set higher
|
274
|
+
# than error and "SHOW standard_conforming_strings" fails, but returns an empty
|
275
|
+
# PGresult instead.
|
276
|
+
has_support = query('SHOW standard_conforming_strings')[0][0] rescue false
|
277
|
+
self.client_min_messages = client_min_messages_old
|
278
|
+
has_support
|
270
279
|
end
|
271
280
|
|
272
281
|
def supports_insert_with_returning?
|
@@ -290,7 +299,7 @@ module ActiveRecord
|
|
290
299
|
# QUOTING ==================================================
|
291
300
|
|
292
301
|
# Escapes binary strings for bytea input to the database.
|
293
|
-
def escape_bytea(
|
302
|
+
def escape_bytea(value)
|
294
303
|
if @connection.respond_to?(:escape_bytea)
|
295
304
|
self.class.instance_eval do
|
296
305
|
define_method(:escape_bytea) do |value|
|
@@ -314,40 +323,62 @@ module ActiveRecord
|
|
314
323
|
end
|
315
324
|
end
|
316
325
|
end
|
317
|
-
escape_bytea(
|
326
|
+
escape_bytea(value)
|
318
327
|
end
|
319
328
|
|
320
329
|
# Unescapes bytea output from a database to the binary string it represents.
|
321
330
|
# NOTE: This is NOT an inverse of escape_bytea! This is only to be used
|
322
331
|
# on escaped binary output from database drive.
|
323
|
-
def unescape_bytea(
|
332
|
+
def unescape_bytea(value)
|
324
333
|
# In each case, check if the value actually is escaped PostgreSQL bytea output
|
325
334
|
# or an unescaped Active Record attribute that was just written.
|
326
|
-
if
|
335
|
+
if PGconn.respond_to?(:unescape_bytea)
|
327
336
|
self.class.instance_eval do
|
328
337
|
define_method(:unescape_bytea) do |value|
|
329
|
-
|
338
|
+
if value =~ /\\\d{3}/
|
339
|
+
PGconn.unescape_bytea(value)
|
340
|
+
else
|
341
|
+
value
|
342
|
+
end
|
330
343
|
end
|
331
344
|
end
|
332
|
-
|
345
|
+
else
|
333
346
|
self.class.instance_eval do
|
334
347
|
define_method(:unescape_bytea) do |value|
|
335
|
-
|
348
|
+
if value =~ /\\\d{3}/
|
349
|
+
result = ''
|
350
|
+
i, max = 0, value.size
|
351
|
+
while i < max
|
352
|
+
char = value[i]
|
353
|
+
if char == ?\\
|
354
|
+
if value[i+1] == ?\\
|
355
|
+
char = ?\\
|
356
|
+
i += 1
|
357
|
+
else
|
358
|
+
char = value[i+1..i+3].oct
|
359
|
+
i += 3
|
360
|
+
end
|
361
|
+
end
|
362
|
+
result << char
|
363
|
+
i += 1
|
364
|
+
end
|
365
|
+
result
|
366
|
+
else
|
367
|
+
value
|
368
|
+
end
|
336
369
|
end
|
337
370
|
end
|
338
|
-
else
|
339
|
-
raise 'Your PostgreSQL connection does not support unescape_bytea. Try upgrading to pg 0.9.0 or later.'
|
340
371
|
end
|
341
|
-
unescape_bytea(
|
372
|
+
unescape_bytea(value)
|
342
373
|
end
|
343
374
|
|
344
375
|
# Quotes PostgreSQL-specific data types for SQL input.
|
345
376
|
def quote(value, column = nil) #:nodoc:
|
346
377
|
if value.kind_of?(String) && column && column.type == :binary
|
347
|
-
"'#{escape_bytea(value)}'"
|
348
|
-
elsif value.kind_of?(String) && column && column.sql_type
|
349
|
-
"xml '#{quote_string(value)}'"
|
350
|
-
elsif value.kind_of?(Numeric) && column && column.sql_type
|
378
|
+
"#{quoted_string_prefix}'#{escape_bytea(value)}'"
|
379
|
+
elsif value.kind_of?(String) && column && column.sql_type =~ /^xml$/
|
380
|
+
"xml E'#{quote_string(value)}'"
|
381
|
+
elsif value.kind_of?(Numeric) && column && column.sql_type =~ /^money$/
|
351
382
|
# Not truly string input, so doesn't require (or allow) escape string syntax.
|
352
383
|
"'#{value.to_s}'"
|
353
384
|
elsif value.kind_of?(String) && column && column.sql_type =~ /^bit/
|
@@ -363,7 +394,7 @@ module ActiveRecord
|
|
363
394
|
end
|
364
395
|
|
365
396
|
# Quotes strings for use in SQL input in the postgres driver for better performance.
|
366
|
-
def quote_string(
|
397
|
+
def quote_string(s) #:nodoc:
|
367
398
|
if @connection.respond_to?(:escape)
|
368
399
|
self.class.instance_eval do
|
369
400
|
define_method(:quote_string) do |s|
|
@@ -383,7 +414,7 @@ module ActiveRecord
|
|
383
414
|
remove_method(:quote_string)
|
384
415
|
end
|
385
416
|
end
|
386
|
-
quote_string(
|
417
|
+
quote_string(s)
|
387
418
|
end
|
388
419
|
|
389
420
|
# Checks the following cases:
|
@@ -479,6 +510,7 @@ module ActiveRecord
|
|
479
510
|
end
|
480
511
|
end
|
481
512
|
end
|
513
|
+
alias :create :insert
|
482
514
|
|
483
515
|
# create a 2D array representing the result set
|
484
516
|
def result_as_array(res) #:nodoc:
|
@@ -859,12 +891,9 @@ module ActiveRecord
|
|
859
891
|
execute "ALTER TABLE #{quote_table_name(table_name)} RENAME COLUMN #{quote_column_name(column_name)} TO #{quote_column_name(new_column_name)}"
|
860
892
|
end
|
861
893
|
|
862
|
-
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
def index_name_length
|
867
|
-
63
|
894
|
+
# Drops an index from a table.
|
895
|
+
def remove_index(table_name, options = {})
|
896
|
+
execute "DROP INDEX #{quote_table_name(index_name(table_name, options))}"
|
868
897
|
end
|
869
898
|
|
870
899
|
# Maps logical Rails types to PostgreSQL-specific data types.
|
@@ -900,20 +929,6 @@ module ActiveRecord
|
|
900
929
|
sql << order_columns * ', '
|
901
930
|
end
|
902
931
|
|
903
|
-
# Returns an ORDER BY clause for the passed order option.
|
904
|
-
#
|
905
|
-
# PostgreSQL does not allow arbitrary ordering when using DISTINCT ON, so we work around this
|
906
|
-
# by wrapping the +sql+ string as a sub-select and ordering in that query.
|
907
|
-
def add_order_by_for_association_limiting!(sql, options) #:nodoc:
|
908
|
-
return sql if options[:order].blank?
|
909
|
-
|
910
|
-
order = options[:order].split(',').collect { |s| s.strip }.reject(&:blank?)
|
911
|
-
order.map! { |s| 'DESC' if s =~ /\bdesc$/i }
|
912
|
-
order = order.zip((0...order.size).to_a).map { |s,i| "id_list.alias_#{i} #{s}" }.join(', ')
|
913
|
-
|
914
|
-
sql.replace "SELECT * FROM (#{sql}) AS id_list ORDER BY #{order}"
|
915
|
-
end
|
916
|
-
|
917
932
|
protected
|
918
933
|
# Returns the version of the connected PostgreSQL version.
|
919
934
|
def postgresql_version
|
@@ -931,6 +946,17 @@ module ActiveRecord
|
|
931
946
|
end
|
932
947
|
end
|
933
948
|
|
949
|
+
def translate_exception(exception, message)
|
950
|
+
case exception.message
|
951
|
+
when /duplicate key value violates unique constraint/
|
952
|
+
RecordNotUnique.new(message, exception)
|
953
|
+
when /violates foreign key constraint/
|
954
|
+
InvalidForeignKey.new(message, exception)
|
955
|
+
else
|
956
|
+
super
|
957
|
+
end
|
958
|
+
end
|
959
|
+
|
934
960
|
private
|
935
961
|
# The internal PostgreSQL identifier of the money data type.
|
936
962
|
MONEY_COLUMN_TYPE_OID = 790 #:nodoc:
|
@@ -944,6 +970,17 @@ module ActiveRecord
|
|
944
970
|
# Ignore async_exec and async_query when using postgres-pr.
|
945
971
|
@async = @config[:allow_concurrency] && @connection.respond_to?(:async_exec)
|
946
972
|
|
973
|
+
# Use escape string syntax if available. We cannot do this lazily when encountering
|
974
|
+
# the first string, because that could then break any transactions in progress.
|
975
|
+
# See: http://www.postgresql.org/docs/current/static/runtime-config-compatible.html
|
976
|
+
# If PostgreSQL doesn't know the standard_conforming_strings parameter then it doesn't
|
977
|
+
# support escape string syntax. Don't override the inherited quoted_string_prefix.
|
978
|
+
if supports_standard_conforming_strings?
|
979
|
+
self.class.instance_eval do
|
980
|
+
define_method(:quoted_string_prefix) { 'E' }
|
981
|
+
end
|
982
|
+
end
|
983
|
+
|
947
984
|
# Money type has a fixed precision of 10 in PostgreSQL 8.2 and below, and as of
|
948
985
|
# PostgreSQL 8.3 it has a fixed precision of 19. PostgreSQLColumn.extract_precision
|
949
986
|
# should know about this but can't detect it there, so deal with it here.
|
@@ -961,7 +998,7 @@ module ActiveRecord
|
|
961
998
|
configure_connection
|
962
999
|
end
|
963
1000
|
|
964
|
-
# Configures the encoding, verbosity,
|
1001
|
+
# Configures the encoding, verbosity, schema search path, and time zone of the connection.
|
965
1002
|
# This is called by #connect and should not be called manually.
|
966
1003
|
def configure_connection
|
967
1004
|
if @config[:encoding]
|
@@ -973,9 +1010,10 @@ module ActiveRecord
|
|
973
1010
|
end
|
974
1011
|
self.client_min_messages = @config[:min_messages] if @config[:min_messages]
|
975
1012
|
self.schema_search_path = @config[:schema_search_path] || @config[:schema_order]
|
976
|
-
|
977
|
-
#
|
978
|
-
|
1013
|
+
|
1014
|
+
# If using ActiveRecord's time zone support configure the connection to return
|
1015
|
+
# TIMESTAMP WITH ZONE types in UTC.
|
1016
|
+
execute("SET time zone 'UTC'") if ActiveRecord::Base.default_timezone == :utc
|
979
1017
|
end
|
980
1018
|
|
981
1019
|
# Returns the current ID of a table's sequence.
|
@@ -24,11 +24,17 @@ module ActiveRecord
|
|
24
24
|
|
25
25
|
module ConnectionAdapters #:nodoc:
|
26
26
|
class SQLite3Adapter < SQLiteAdapter # :nodoc:
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
|
28
|
+
# Returns the current database encoding format as a string, eg: 'UTF-8'
|
29
|
+
def encoding
|
30
|
+
if @connection.respond_to?(:encoding)
|
31
|
+
@connection.encoding[0]['encoding']
|
32
|
+
else
|
33
|
+
encoding = @connection.send(:get_query_pragma, 'encoding')
|
34
|
+
encoding[0]['encoding']
|
30
35
|
end
|
31
36
|
end
|
37
|
+
|
32
38
|
end
|
33
39
|
end
|
34
40
|
end
|
@@ -1,51 +1,21 @@
|
|
1
|
-
# encoding: binary
|
2
1
|
require 'active_record/connection_adapters/abstract_adapter'
|
2
|
+
require 'active_support/core_ext/kernel/requires'
|
3
3
|
|
4
4
|
module ActiveRecord
|
5
5
|
class Base
|
6
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
7
|
private
|
33
8
|
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
9
|
# Require database.
|
40
10
|
unless config[:database]
|
41
11
|
raise ArgumentError, "No database file specified. Missing argument: database"
|
42
12
|
end
|
43
13
|
|
44
|
-
# Allow database path relative to
|
14
|
+
# Allow database path relative to Rails.root, but only if
|
45
15
|
# the database path is not the special path that tells
|
46
16
|
# Sqlite to build a database only in memory.
|
47
|
-
if
|
48
|
-
config[:database] = File.expand_path(config[:database],
|
17
|
+
if defined?(Rails.root) && ':memory:' != config[:database]
|
18
|
+
config[:database] = File.expand_path(config[:database], Rails.root)
|
49
19
|
end
|
50
20
|
end
|
51
21
|
end
|
@@ -55,7 +25,6 @@ module ActiveRecord
|
|
55
25
|
class SQLiteColumn < Column #:nodoc:
|
56
26
|
class << self
|
57
27
|
def string_to_binary(value)
|
58
|
-
value = value.dup.force_encoding(Encoding::BINARY) if value.respond_to?(:force_encoding)
|
59
28
|
value.gsub(/\0|\%/n) do |b|
|
60
29
|
case b
|
61
30
|
when "\0" then "%00"
|
@@ -65,7 +34,6 @@ module ActiveRecord
|
|
65
34
|
end
|
66
35
|
|
67
36
|
def binary_to_string(value)
|
68
|
-
value = value.dup.force_encoding(Encoding::BINARY) if value.respond_to?(:force_encoding)
|
69
37
|
value.gsub(/%00|%25/n) do |b|
|
70
38
|
case b
|
71
39
|
when "%00" then "\0"
|
@@ -123,7 +91,7 @@ module ActiveRecord
|
|
123
91
|
def supports_add_column?
|
124
92
|
sqlite_version >= '3.1.6'
|
125
93
|
end
|
126
|
-
|
94
|
+
|
127
95
|
def disconnect!
|
128
96
|
super
|
129
97
|
@connection.close rescue nil
|
@@ -162,7 +130,17 @@ module ActiveRecord
|
|
162
130
|
end
|
163
131
|
|
164
132
|
def quote_column_name(name) #:nodoc:
|
165
|
-
%Q("#{name
|
133
|
+
%Q("#{name}")
|
134
|
+
end
|
135
|
+
|
136
|
+
# Quote date/time values for use in SQL input. Includes microseconds
|
137
|
+
# if the value is a Time responding to usec.
|
138
|
+
def quoted_date(value) #:nodoc:
|
139
|
+
if value.acts_like?(:time) && value.respond_to?(:usec)
|
140
|
+
"#{super}.#{sprintf("%06d", value.usec)}"
|
141
|
+
else
|
142
|
+
super
|
143
|
+
end
|
166
144
|
end
|
167
145
|
|
168
146
|
|
@@ -185,6 +163,7 @@ module ActiveRecord
|
|
185
163
|
def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
|
186
164
|
super || @connection.last_insert_row_id
|
187
165
|
end
|
166
|
+
alias :create :insert_sql
|
188
167
|
|
189
168
|
def select_rows(sql, name = nil)
|
190
169
|
execute(sql, name).map do |row|
|
@@ -204,12 +183,6 @@ module ActiveRecord
|
|
204
183
|
catch_schema_changes { @connection.rollback }
|
205
184
|
end
|
206
185
|
|
207
|
-
# SELECT ... FOR UPDATE is redundant since the table is locked.
|
208
|
-
def add_lock!(sql, options) #:nodoc:
|
209
|
-
sql
|
210
|
-
end
|
211
|
-
|
212
|
-
|
213
186
|
# SCHEMA STATEMENTS ========================================
|
214
187
|
|
215
188
|
def tables(name = nil) #:nodoc:
|
@@ -244,12 +217,12 @@ module ActiveRecord
|
|
244
217
|
column ? column['name'] : nil
|
245
218
|
end
|
246
219
|
|
247
|
-
def remove_index
|
248
|
-
execute "DROP INDEX #{quote_column_name(index_name)}"
|
220
|
+
def remove_index(table_name, options={}) #:nodoc:
|
221
|
+
execute "DROP INDEX #{quote_column_name(index_name(table_name, options))}"
|
249
222
|
end
|
250
223
|
|
251
224
|
def rename_table(name, new_name)
|
252
|
-
execute "ALTER TABLE #{name} RENAME TO #{new_name}"
|
225
|
+
execute "ALTER TABLE #{quote_table_name(name)} RENAME TO #{quote_table_name(new_name)}"
|
253
226
|
end
|
254
227
|
|
255
228
|
# See: http://www.sqlite.org/lang_altertable.html
|
@@ -269,7 +242,6 @@ module ActiveRecord
|
|
269
242
|
end
|
270
243
|
|
271
244
|
def remove_column(table_name, *column_names) #:nodoc:
|
272
|
-
raise ArgumentError.new("You must specify at least one column name. Example: remove_column(:people, :first_name)") if column_names.empty?
|
273
245
|
column_names.flatten.each do |column_name|
|
274
246
|
alter_table(table_name) do |definition|
|
275
247
|
definition.columns.delete(definition[column_name])
|
@@ -312,8 +284,8 @@ module ActiveRecord
|
|
312
284
|
alter_table(table_name, :rename => {column_name.to_s => new_column_name.to_s})
|
313
285
|
end
|
314
286
|
|
315
|
-
def
|
316
|
-
"
|
287
|
+
def empty_insert_statement_value
|
288
|
+
"VALUES(NULL)"
|
317
289
|
end
|
318
290
|
|
319
291
|
protected
|
@@ -330,9 +302,9 @@ module ActiveRecord
|
|
330
302
|
end
|
331
303
|
|
332
304
|
def table_structure(table_name)
|
333
|
-
|
334
|
-
|
335
|
-
|
305
|
+
structure = @connection.table_info(quote_table_name(table_name))
|
306
|
+
raise(ActiveRecord::StatementInvalid, "Could not find table '#{table_name}'") if structure.empty?
|
307
|
+
structure
|
336
308
|
end
|
337
309
|
|
338
310
|
def alter_table(table_name, options = {}) #:nodoc:
|
@@ -360,7 +332,7 @@ module ActiveRecord
|
|
360
332
|
(options[:rename][column.name] ||
|
361
333
|
options[:rename][column.name.to_sym] ||
|
362
334
|
column.name) : column.name
|
363
|
-
|
335
|
+
|
364
336
|
@definition.column(column_name, column.type,
|
365
337
|
:limit => column.limit, :default => column.default,
|
366
338
|
:null => column.null)
|
@@ -436,19 +408,16 @@ module ActiveRecord
|
|
436
408
|
'INTEGER PRIMARY KEY NOT NULL'.freeze
|
437
409
|
end
|
438
410
|
end
|
439
|
-
end
|
440
411
|
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
412
|
+
def translate_exception(exception, message)
|
413
|
+
case exception.message
|
414
|
+
when /column(s)? .* (is|are) not unique/
|
415
|
+
RecordNotUnique.new(message, exception)
|
416
|
+
else
|
417
|
+
super
|
418
|
+
end
|
419
|
+
end
|
446
420
|
|
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
421
|
end
|
453
422
|
end
|
454
423
|
end
|