activerecord 1.0.0 → 2.0.0
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 +4928 -3
- data/README +45 -46
- data/RUNNING_UNIT_TESTS +8 -11
- data/Rakefile +247 -0
- data/install.rb +8 -38
- data/lib/active_record/aggregations.rb +64 -49
- data/lib/active_record/associations/association_collection.rb +217 -47
- data/lib/active_record/associations/association_proxy.rb +159 -0
- data/lib/active_record/associations/belongs_to_association.rb +56 -0
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +50 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +155 -37
- data/lib/active_record/associations/has_many_association.rb +145 -75
- data/lib/active_record/associations/has_many_through_association.rb +283 -0
- data/lib/active_record/associations/has_one_association.rb +96 -0
- data/lib/active_record/associations.rb +1537 -304
- data/lib/active_record/attribute_methods.rb +328 -0
- data/lib/active_record/base.rb +2001 -588
- data/lib/active_record/calculations.rb +269 -0
- data/lib/active_record/callbacks.rb +169 -165
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +308 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +171 -0
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +87 -0
- data/lib/active_record/connection_adapters/abstract/quoting.rb +69 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +472 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +306 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +125 -279
- data/lib/active_record/connection_adapters/mysql_adapter.rb +442 -77
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +805 -135
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +34 -0
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +353 -69
- data/lib/active_record/fixtures.rb +946 -100
- data/lib/active_record/locking/optimistic.rb +144 -0
- data/lib/active_record/locking/pessimistic.rb +77 -0
- data/lib/active_record/migration.rb +417 -0
- data/lib/active_record/observer.rb +142 -32
- data/lib/active_record/query_cache.rb +23 -0
- data/lib/active_record/reflection.rb +163 -70
- data/lib/active_record/schema.rb +58 -0
- data/lib/active_record/schema_dumper.rb +171 -0
- data/lib/active_record/serialization.rb +98 -0
- data/lib/active_record/serializers/json_serializer.rb +71 -0
- data/lib/active_record/serializers/xml_serializer.rb +315 -0
- data/lib/active_record/timestamp.rb +41 -0
- data/lib/active_record/transactions.rb +87 -57
- data/lib/active_record/validations.rb +909 -122
- data/lib/active_record/vendor/db2.rb +362 -0
- data/lib/active_record/vendor/mysql.rb +126 -29
- data/lib/active_record/version.rb +9 -0
- data/lib/active_record.rb +35 -7
- data/lib/activerecord.rb +1 -0
- data/test/aaa_create_tables_test.rb +72 -0
- data/test/abstract_unit.rb +73 -5
- data/test/active_schema_test_mysql.rb +43 -0
- data/test/adapter_test.rb +105 -0
- data/test/adapter_test_sqlserver.rb +95 -0
- data/test/aggregations_test.rb +110 -16
- data/test/all.sh +2 -2
- data/test/ar_schema_test.rb +33 -0
- data/test/association_inheritance_reload.rb +14 -0
- data/test/associations/ar_joins_test.rb +0 -0
- data/test/associations/callbacks_test.rb +147 -0
- data/test/associations/cascaded_eager_loading_test.rb +110 -0
- data/test/associations/eager_singularization_test.rb +145 -0
- data/test/associations/eager_test.rb +442 -0
- data/test/associations/extension_test.rb +47 -0
- data/test/associations/inner_join_association_test.rb +88 -0
- data/test/associations/join_model_test.rb +553 -0
- data/test/associations_test.rb +1930 -267
- data/test/attribute_methods_test.rb +146 -0
- data/test/base_test.rb +1316 -84
- data/test/binary_test.rb +32 -0
- data/test/calculations_test.rb +251 -0
- data/test/callbacks_test.rb +400 -0
- data/test/class_inheritable_attributes_test.rb +3 -4
- data/test/column_alias_test.rb +17 -0
- data/test/connection_test_firebird.rb +8 -0
- data/test/connection_test_mysql.rb +30 -0
- data/test/connections/native_db2/connection.rb +25 -0
- data/test/connections/native_firebird/connection.rb +26 -0
- data/test/connections/native_frontbase/connection.rb +27 -0
- data/test/connections/native_mysql/connection.rb +21 -18
- data/test/connections/native_openbase/connection.rb +21 -0
- data/test/connections/native_oracle/connection.rb +27 -0
- data/test/connections/native_postgresql/connection.rb +17 -18
- data/test/connections/native_sqlite/connection.rb +17 -16
- data/test/connections/native_sqlite3/connection.rb +25 -0
- data/test/connections/native_sqlite3/in_memory_connection.rb +18 -0
- data/test/connections/native_sybase/connection.rb +23 -0
- data/test/copy_table_test_sqlite.rb +69 -0
- data/test/datatype_test_postgresql.rb +203 -0
- data/test/date_time_test.rb +37 -0
- data/test/default_test_firebird.rb +16 -0
- data/test/defaults_test.rb +67 -0
- data/test/deprecated_finder_test.rb +30 -0
- data/test/finder_test.rb +607 -32
- data/test/fixtures/accounts.yml +28 -0
- 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.rb +107 -0
- data/test/fixtures/author_favorites.yml +4 -0
- data/test/fixtures/authors.yml +7 -0
- data/test/fixtures/bad_fixtures/attr_with_numeric_first_char +1 -0
- data/test/fixtures/bad_fixtures/attr_with_spaces +1 -0
- data/test/fixtures/bad_fixtures/blank_line +3 -0
- data/test/fixtures/bad_fixtures/duplicate_attributes +3 -0
- data/test/fixtures/bad_fixtures/missing_value +1 -0
- data/test/fixtures/binaries.yml +132 -0
- data/test/fixtures/binary.rb +2 -0
- data/test/fixtures/book.rb +4 -0
- data/test/fixtures/books.yml +7 -0
- data/test/fixtures/categories/special_categories.yml +9 -0
- data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -0
- data/test/fixtures/categories.yml +14 -0
- data/test/fixtures/categories_ordered.yml +7 -0
- data/test/fixtures/categories_posts.yml +23 -0
- data/test/fixtures/categorization.rb +5 -0
- data/test/fixtures/categorizations.yml +17 -0
- data/test/fixtures/category.rb +26 -0
- data/test/fixtures/citation.rb +6 -0
- data/test/fixtures/comment.rb +23 -0
- data/test/fixtures/comments.yml +59 -0
- data/test/fixtures/companies.yml +55 -0
- data/test/fixtures/company.rb +81 -4
- data/test/fixtures/company_in_module.rb +32 -6
- data/test/fixtures/computer.rb +4 -0
- data/test/fixtures/computers.yml +4 -0
- data/test/fixtures/contact.rb +16 -0
- data/test/fixtures/courses.yml +7 -0
- data/test/fixtures/customer.rb +28 -3
- data/test/fixtures/customers.yml +17 -0
- data/test/fixtures/db_definitions/db2.drop.sql +33 -0
- data/test/fixtures/db_definitions/db2.sql +235 -0
- data/test/fixtures/db_definitions/db22.drop.sql +2 -0
- data/test/fixtures/db_definitions/db22.sql +5 -0
- data/test/fixtures/db_definitions/firebird.drop.sql +65 -0
- data/test/fixtures/db_definitions/firebird.sql +310 -0
- data/test/fixtures/db_definitions/firebird2.drop.sql +2 -0
- data/test/fixtures/db_definitions/firebird2.sql +6 -0
- data/test/fixtures/db_definitions/frontbase.drop.sql +33 -0
- data/test/fixtures/db_definitions/frontbase.sql +273 -0
- data/test/fixtures/db_definitions/frontbase2.drop.sql +1 -0
- data/test/fixtures/db_definitions/frontbase2.sql +4 -0
- data/test/fixtures/db_definitions/openbase.drop.sql +2 -0
- data/test/fixtures/db_definitions/openbase.sql +318 -0
- data/test/fixtures/db_definitions/openbase2.drop.sql +2 -0
- data/test/fixtures/db_definitions/openbase2.sql +7 -0
- data/test/fixtures/db_definitions/oracle.drop.sql +67 -0
- data/test/fixtures/db_definitions/oracle.sql +330 -0
- data/test/fixtures/db_definitions/oracle2.drop.sql +2 -0
- data/test/fixtures/db_definitions/oracle2.sql +6 -0
- data/test/fixtures/db_definitions/postgresql.drop.sql +44 -0
- data/test/fixtures/db_definitions/postgresql.sql +217 -38
- data/test/fixtures/db_definitions/postgresql2.drop.sql +2 -0
- data/test/fixtures/db_definitions/postgresql2.sql +2 -2
- data/test/fixtures/db_definitions/schema.rb +354 -0
- data/test/fixtures/db_definitions/schema2.rb +11 -0
- data/test/fixtures/db_definitions/sqlite.drop.sql +33 -0
- data/test/fixtures/db_definitions/sqlite.sql +139 -5
- data/test/fixtures/db_definitions/sqlite2.drop.sql +2 -0
- data/test/fixtures/db_definitions/sqlite2.sql +1 -0
- data/test/fixtures/db_definitions/sybase.drop.sql +35 -0
- data/test/fixtures/db_definitions/sybase.sql +222 -0
- data/test/fixtures/db_definitions/sybase2.drop.sql +4 -0
- data/test/fixtures/db_definitions/sybase2.sql +5 -0
- data/test/fixtures/developer.rb +70 -6
- data/test/fixtures/developers.yml +21 -0
- data/test/fixtures/developers_projects/david_action_controller +2 -1
- data/test/fixtures/developers_projects/david_active_record +2 -1
- data/test/fixtures/developers_projects.yml +17 -0
- data/test/fixtures/edge.rb +5 -0
- data/test/fixtures/edges.yml +6 -0
- data/test/fixtures/entrants.yml +14 -0
- data/test/fixtures/example.log +1 -0
- data/test/fixtures/fk_test_has_fk.yml +3 -0
- data/test/fixtures/fk_test_has_pk.yml +2 -0
- data/test/fixtures/flowers.jpg +0 -0
- data/test/fixtures/funny_jokes.yml +10 -0
- data/test/fixtures/item.rb +7 -0
- data/test/fixtures/items.yml +4 -0
- data/test/fixtures/joke.rb +3 -0
- data/test/fixtures/keyboard.rb +3 -0
- data/test/fixtures/legacy_thing.rb +3 -0
- data/test/fixtures/legacy_things.yml +3 -0
- data/test/fixtures/matey.rb +4 -0
- data/test/fixtures/mateys.yml +4 -0
- data/test/fixtures/migrations/1_people_have_last_names.rb +9 -0
- data/test/fixtures/migrations/2_we_need_reminders.rb +12 -0
- data/test/fixtures/migrations/3_innocent_jointable.rb +12 -0
- data/test/fixtures/migrations_with_decimal/1_give_me_big_numbers.rb +15 -0
- data/test/fixtures/migrations_with_duplicate/1_people_have_last_names.rb +9 -0
- data/test/fixtures/migrations_with_duplicate/2_we_need_reminders.rb +12 -0
- data/test/fixtures/migrations_with_duplicate/3_foo.rb +7 -0
- data/test/fixtures/migrations_with_duplicate/3_innocent_jointable.rb +12 -0
- data/test/fixtures/migrations_with_missing_versions/1000_people_have_middle_names.rb +9 -0
- data/test/fixtures/migrations_with_missing_versions/1_people_have_last_names.rb +9 -0
- data/test/fixtures/migrations_with_missing_versions/3_we_need_reminders.rb +12 -0
- data/test/fixtures/migrations_with_missing_versions/4_innocent_jointable.rb +12 -0
- data/test/fixtures/minimalistic.rb +2 -0
- data/test/fixtures/minimalistics.yml +2 -0
- data/test/fixtures/mixed_case_monkey.rb +3 -0
- data/test/fixtures/mixed_case_monkeys.yml +6 -0
- data/test/fixtures/mixins.yml +29 -0
- data/test/fixtures/movies.yml +7 -0
- data/test/fixtures/naked/csv/accounts.csv +1 -0
- data/test/fixtures/naked/yml/accounts.yml +1 -0
- data/test/fixtures/naked/yml/companies.yml +1 -0
- data/test/fixtures/naked/yml/courses.yml +1 -0
- data/test/fixtures/order.rb +4 -0
- data/test/fixtures/parrot.rb +13 -0
- data/test/fixtures/parrots.yml +27 -0
- data/test/fixtures/parrots_pirates.yml +7 -0
- data/test/fixtures/people.yml +3 -0
- data/test/fixtures/person.rb +4 -0
- data/test/fixtures/pirate.rb +5 -0
- data/test/fixtures/pirates.yml +9 -0
- data/test/fixtures/post.rb +59 -0
- data/test/fixtures/posts.yml +48 -0
- data/test/fixtures/project.rb +27 -2
- data/test/fixtures/projects.yml +7 -0
- data/test/fixtures/reader.rb +4 -0
- data/test/fixtures/readers.yml +4 -0
- data/test/fixtures/reply.rb +18 -2
- data/test/fixtures/reserved_words/distinct.yml +5 -0
- data/test/fixtures/reserved_words/distincts_selects.yml +11 -0
- data/test/fixtures/reserved_words/group.yml +14 -0
- data/test/fixtures/reserved_words/select.yml +8 -0
- data/test/fixtures/reserved_words/values.yml +7 -0
- data/test/fixtures/ship.rb +3 -0
- data/test/fixtures/ships.yml +5 -0
- data/test/fixtures/subject.rb +4 -0
- data/test/fixtures/subscriber.rb +4 -3
- data/test/fixtures/tag.rb +7 -0
- data/test/fixtures/tagging.rb +10 -0
- data/test/fixtures/taggings.yml +25 -0
- data/test/fixtures/tags.yml +7 -0
- data/test/fixtures/task.rb +3 -0
- data/test/fixtures/tasks.yml +7 -0
- data/test/fixtures/topic.rb +20 -3
- data/test/fixtures/topics.yml +22 -0
- data/test/fixtures/treasure.rb +4 -0
- data/test/fixtures/treasures.yml +10 -0
- data/test/fixtures/vertex.rb +9 -0
- data/test/fixtures/vertices.yml +4 -0
- data/test/fixtures_test.rb +574 -8
- data/test/inheritance_test.rb +113 -27
- data/test/json_serialization_test.rb +180 -0
- data/test/lifecycle_test.rb +56 -29
- data/test/locking_test.rb +273 -0
- data/test/method_scoping_test.rb +416 -0
- data/test/migration_test.rb +933 -0
- data/test/migration_test_firebird.rb +124 -0
- data/test/mixin_test.rb +95 -0
- data/test/modules_test.rb +23 -10
- data/test/multiple_db_test.rb +17 -3
- data/test/pk_test.rb +59 -15
- data/test/query_cache_test.rb +104 -0
- data/test/readonly_test.rb +107 -0
- data/test/reflection_test.rb +124 -27
- data/test/reserved_word_test_mysql.rb +177 -0
- data/test/schema_authorization_test_postgresql.rb +75 -0
- data/test/schema_dumper_test.rb +131 -0
- data/test/schema_test_postgresql.rb +64 -0
- data/test/serialization_test.rb +47 -0
- data/test/synonym_test_oracle.rb +17 -0
- data/test/table_name_test_sqlserver.rb +23 -0
- data/test/threaded_connections_test.rb +48 -0
- data/test/transactions_test.rb +227 -29
- data/test/unconnected_test.rb +14 -6
- data/test/validations_test.rb +1293 -32
- data/test/xml_serialization_test.rb +202 -0
- metadata +347 -143
- data/dev-utils/eval_debugger.rb +0 -9
- data/examples/associations.rb +0 -87
- data/examples/shared_setup.rb +0 -15
- data/examples/validation.rb +0 -88
- data/lib/active_record/deprecated_associations.rb +0 -70
- data/lib/active_record/support/class_attribute_accessors.rb +0 -43
- data/lib/active_record/support/class_inheritable_attributes.rb +0 -37
- data/lib/active_record/support/clean_logger.rb +0 -10
- data/lib/active_record/support/inflector.rb +0 -70
- data/lib/active_record/vendor/simple.rb +0 -702
- data/lib/active_record/wrappers/yaml_wrapper.rb +0 -15
- data/lib/active_record/wrappings.rb +0 -59
- data/rakefile +0 -122
- data/test/deprecated_associations_test.rb +0 -336
- data/test/fixtures/accounts/signals37 +0 -3
- data/test/fixtures/accounts/unknown +0 -2
- data/test/fixtures/companies/first_client +0 -6
- data/test/fixtures/companies/first_firm +0 -4
- data/test/fixtures/companies/second_client +0 -6
- data/test/fixtures/courses/java +0 -2
- data/test/fixtures/courses/ruby +0 -2
- data/test/fixtures/customers/david +0 -6
- data/test/fixtures/db_definitions/mysql.sql +0 -96
- data/test/fixtures/db_definitions/mysql2.sql +0 -4
- data/test/fixtures/developers/david +0 -2
- data/test/fixtures/developers/jamis +0 -2
- data/test/fixtures/entrants/first +0 -3
- data/test/fixtures/entrants/second +0 -3
- data/test/fixtures/entrants/third +0 -3
- data/test/fixtures/fixture_database.sqlite +0 -0
- data/test/fixtures/fixture_database_2.sqlite +0 -0
- data/test/fixtures/movies/first +0 -2
- data/test/fixtures/movies/second +0 -2
- data/test/fixtures/projects/action_controller +0 -2
- data/test/fixtures/projects/active_record +0 -2
- data/test/fixtures/topics/first +0 -9
- data/test/fixtures/topics/second +0 -8
- data/test/inflector_test.rb +0 -104
- data/test/thread_safety_test.rb +0 -33
@@ -1,325 +1,171 @@
|
|
1
1
|
require 'benchmark'
|
2
2
|
require 'date'
|
3
|
+
require 'bigdecimal'
|
4
|
+
require 'bigdecimal/util'
|
3
5
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
11
|
-
end
|
6
|
+
require 'active_record/connection_adapters/abstract/schema_definitions'
|
7
|
+
require 'active_record/connection_adapters/abstract/schema_statements'
|
8
|
+
require 'active_record/connection_adapters/abstract/database_statements'
|
9
|
+
require 'active_record/connection_adapters/abstract/quoting'
|
10
|
+
require 'active_record/connection_adapters/abstract/connection_specification'
|
11
|
+
require 'active_record/connection_adapters/abstract/query_cache'
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
#
|
17
|
-
#
|
18
|
-
# example for regular databases (MySQL, Postgresql, etc):
|
19
|
-
#
|
20
|
-
# ActiveRecord::Base.establish_connection(
|
21
|
-
# :adapter => "mysql",
|
22
|
-
# :host => "localhost",
|
23
|
-
# :username => "myuser",
|
24
|
-
# :password => "mypass",
|
25
|
-
# :database => "somedatabase"
|
26
|
-
# )
|
27
|
-
#
|
28
|
-
# Example for SQLite database:
|
29
|
-
#
|
30
|
-
# ActiveRecord::Base.establish_connection(
|
31
|
-
# :adapter => "sqlite",
|
32
|
-
# :dbfile => "path/to/dbfile"
|
33
|
-
# )
|
34
|
-
#
|
35
|
-
# Also accepts keys as strings (for parsing from yaml for example):
|
36
|
-
# ActiveRecord::Base.establish_connection(
|
37
|
-
# "adapter" => "sqlite",
|
38
|
-
# "dbfile" => "path/to/dbfile"
|
39
|
-
# )
|
40
|
-
#
|
41
|
-
# The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError
|
42
|
-
# may be returned on an error.
|
43
|
-
#
|
44
|
-
# == Connecting to another database for a single model
|
45
|
-
#
|
46
|
-
# To support different connections for different classes, you can
|
47
|
-
# simply call establish_connection with the classes you wish to have
|
48
|
-
# different connections for:
|
49
|
-
#
|
50
|
-
# class Courses < ActiveRecord::Base
|
51
|
-
# ...
|
52
|
-
# end
|
13
|
+
module ActiveRecord
|
14
|
+
module ConnectionAdapters # :nodoc:
|
15
|
+
# All the concrete database adapters follow the interface laid down in this class.
|
16
|
+
# You can use this interface directly by borrowing the database connection from the Base with
|
17
|
+
# Base.connection.
|
53
18
|
#
|
54
|
-
#
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
adapter_method = "#{spec[:adapter]}_connection"
|
64
|
-
unless methods.include?(adapter_method) then raise AdapterNotFound end
|
65
|
-
remove_connection
|
66
|
-
@@defined_connections[self] = ConnectionSpecification.new(spec, adapter_method)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
# Locate the connection of the nearest super class. This can be an
|
71
|
-
# active or defined connections: if it is the latter, it will be
|
72
|
-
# opened and set as the active connection for the class it was defined
|
73
|
-
# for (not necessarily the current class).
|
74
|
-
def self.retrieve_connection #:nodoc:
|
75
|
-
klass = self
|
76
|
-
until klass == ActiveRecord::Base.superclass
|
77
|
-
Thread.current['active_connections'] ||= {}
|
78
|
-
if Thread.current['active_connections'][klass]
|
79
|
-
return Thread.current['active_connections'][klass]
|
80
|
-
elsif @@defined_connections[klass]
|
81
|
-
klass.connection = @@defined_connections[klass]
|
82
|
-
return self.connection
|
83
|
-
end
|
84
|
-
klass = klass.superclass
|
85
|
-
end
|
86
|
-
raise ConnectionNotEstablished
|
87
|
-
end
|
88
|
-
|
89
|
-
# Returns true if a connection that's accessible to this class have already been opened.
|
90
|
-
def self.connected?
|
91
|
-
klass = self
|
92
|
-
until klass == ActiveRecord::Base.superclass
|
93
|
-
if Thread.current['active_connections'].is_a?(Hash) && Thread.current['active_connections'][klass]
|
94
|
-
return true
|
95
|
-
else
|
96
|
-
klass = klass.superclass
|
97
|
-
end
|
98
|
-
end
|
99
|
-
return false
|
100
|
-
end
|
101
|
-
|
102
|
-
# Remove the connection for this class. This will close the active
|
103
|
-
# connection and the defined connection (if they exist). The result
|
104
|
-
# can be used as argument for establish_connection, for easy
|
105
|
-
# re-establishing of the connection.
|
106
|
-
def self.remove_connection(klass=self)
|
107
|
-
conn = @@defined_connections[klass]
|
108
|
-
@@defined_connections.delete(klass)
|
109
|
-
Thread.current['active_connections'] ||= {}
|
110
|
-
Thread.current['active_connections'][klass] = nil
|
111
|
-
conn.config if conn
|
112
|
-
end
|
113
|
-
|
114
|
-
# Set the connection for the class.
|
115
|
-
def self.connection=(spec)
|
116
|
-
raise ConnectionNotEstablished unless spec
|
117
|
-
conn = self.send(spec.adapter_method, spec.config)
|
118
|
-
Thread.current['active_connections'] ||= {}
|
119
|
-
Thread.current['active_connections'][self] = conn
|
120
|
-
end
|
19
|
+
# Most of the methods in the adapter are useful during migrations. Most
|
20
|
+
# notably, SchemaStatements#create_table, SchemaStatements#drop_table,
|
21
|
+
# SchemaStatements#add_index, SchemaStatements#remove_index,
|
22
|
+
# SchemaStatements#add_column, SchemaStatements#change_column and
|
23
|
+
# SchemaStatements#remove_column are very useful.
|
24
|
+
class AbstractAdapter
|
25
|
+
include Quoting, DatabaseStatements, SchemaStatements
|
26
|
+
include QueryCache
|
27
|
+
@@row_even = true
|
121
28
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
hash.delete key
|
127
|
-
hash[key.intern] = value
|
128
|
-
end
|
29
|
+
def initialize(connection, logger = nil) #:nodoc:
|
30
|
+
@connection, @logger = connection, logger
|
31
|
+
@runtime = 0
|
32
|
+
@last_verification = 0
|
129
33
|
end
|
130
|
-
end
|
131
|
-
end
|
132
34
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
# The default should contain the type-casted default of the column, such as 1 in "count int(11) DEFAULT 1"
|
138
|
-
# The type parameter should either contain :integer, :float, :datetime, :date, :text, or :string
|
139
|
-
# The sql_type is just used for extracting the limit, such as 10 in "varchar(10)"
|
140
|
-
def initialize(name, default, sql_type = nil)
|
141
|
-
@name, @default, @type = name, default, simplified_type(sql_type)
|
142
|
-
@limit = extract_limit(sql_type) unless sql_type.nil?
|
35
|
+
# Returns the human-readable name of the adapter. Use mixed case - one
|
36
|
+
# can always use downcase if needed.
|
37
|
+
def adapter_name
|
38
|
+
'Abstract'
|
143
39
|
end
|
144
40
|
|
145
|
-
|
146
|
-
|
41
|
+
# Does this adapter support migrations? Backend specific, as the
|
42
|
+
# abstract adapter always returns +false+.
|
43
|
+
def supports_migrations?
|
44
|
+
false
|
147
45
|
end
|
148
46
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
when :datetime then Time
|
154
|
-
when :date then Date
|
155
|
-
when :text, :string then String
|
156
|
-
when :boolean then Object
|
157
|
-
end
|
47
|
+
# Does this adapter support using DISTINCT within COUNT? This is +true+
|
48
|
+
# for all adapters except sqlite.
|
49
|
+
def supports_count_distinct?
|
50
|
+
true
|
158
51
|
end
|
159
|
-
|
160
|
-
def type_cast(value)
|
161
|
-
if value.nil? then return nil end
|
162
|
-
case type
|
163
|
-
when :string then value
|
164
|
-
when :text then value
|
165
|
-
when :integer then value.to_i
|
166
|
-
when :float then value.to_f
|
167
|
-
when :datetime then string_to_time(value)
|
168
|
-
when :date then string_to_date(value)
|
169
|
-
when :boolean then (value == "t" or value == true ? true : false)
|
170
|
-
else value
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
def human_name
|
175
|
-
Base.human_attribute_name(@name)
|
176
|
-
end
|
177
|
-
|
178
|
-
private
|
179
|
-
def string_to_date(string)
|
180
|
-
return string if Date === string
|
181
|
-
date_array = ParseDate.parsedate(string)
|
182
|
-
# treat 0000-00-00 as nil
|
183
|
-
Date.new(date_array[0], date_array[1], date_array[2]) rescue nil
|
184
|
-
end
|
185
|
-
|
186
|
-
def string_to_time(string)
|
187
|
-
return string if Time === string
|
188
|
-
time_array = ParseDate.parsedate(string).compact
|
189
|
-
# treat 0000-00-00 00:00:00 as nil
|
190
|
-
Time.local(*time_array) rescue nil
|
191
|
-
end
|
192
52
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
:integer
|
201
|
-
when /float|double|decimal|numeric/i
|
202
|
-
:float
|
203
|
-
when /time/i
|
204
|
-
:datetime
|
205
|
-
when /date/i
|
206
|
-
:date
|
207
|
-
when /(c|b)lob/i, /text/i
|
208
|
-
:text
|
209
|
-
when /char/i, /string/i
|
210
|
-
:string
|
211
|
-
when /boolean/i
|
212
|
-
:boolean
|
213
|
-
end
|
214
|
-
end
|
215
|
-
end
|
53
|
+
# Should primary key values be selected from their corresponding
|
54
|
+
# sequence before the insert statement? If true, next_sequence_value
|
55
|
+
# is called before each insert to set the record's primary key.
|
56
|
+
# This is false for all adapters but Firebird.
|
57
|
+
def prefetch_primary_key?(table_name = nil)
|
58
|
+
false
|
59
|
+
end
|
216
60
|
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
@@row_even = true
|
61
|
+
def reset_runtime #:nodoc:
|
62
|
+
rt, @runtime = @runtime, 0
|
63
|
+
rt
|
64
|
+
end
|
222
65
|
|
223
|
-
|
66
|
+
# QUOTING ==================================================
|
224
67
|
|
225
|
-
|
226
|
-
|
227
|
-
|
68
|
+
# Override to return the quoted table name if the database needs it
|
69
|
+
def quote_table_name(name)
|
70
|
+
name
|
228
71
|
end
|
229
72
|
|
230
|
-
#
|
231
|
-
def select_all(sql, name = nil) end
|
232
|
-
|
233
|
-
# Returns a record hash with the column names as a keys and fields as values.
|
234
|
-
def select_one(sql, name = nil) end
|
235
|
-
|
236
|
-
# Returns an array of column objects for the table specified by +table_name+.
|
237
|
-
def columns(table_name, name = nil) end
|
73
|
+
# REFERENTIAL INTEGRITY ====================================
|
238
74
|
|
239
|
-
#
|
240
|
-
def
|
75
|
+
# Override to turn off referential integrity while executing +&block+
|
76
|
+
def disable_referential_integrity(&block)
|
77
|
+
yield
|
78
|
+
end
|
241
79
|
|
242
|
-
#
|
243
|
-
def update(sql, name = nil) end
|
80
|
+
# CONNECTION MANAGEMENT ====================================
|
244
81
|
|
245
|
-
#
|
246
|
-
def
|
82
|
+
# Is this connection active and ready to perform queries?
|
83
|
+
def active?
|
84
|
+
@active != false
|
85
|
+
end
|
247
86
|
|
248
|
-
|
249
|
-
|
250
|
-
@
|
251
|
-
return rt
|
87
|
+
# Close this connection and open a new one in its place.
|
88
|
+
def reconnect!
|
89
|
+
@active = true
|
252
90
|
end
|
253
91
|
|
254
|
-
#
|
255
|
-
def
|
256
|
-
|
257
|
-
|
258
|
-
def commit_db_transaction() end
|
92
|
+
# Close this connection
|
93
|
+
def disconnect!
|
94
|
+
@active = false
|
95
|
+
end
|
259
96
|
|
260
|
-
#
|
261
|
-
#
|
262
|
-
def
|
97
|
+
# Returns true if its safe to reload the connection between requests for development mode.
|
98
|
+
# This is not the case for Ruby/MySQL and it's not necessary for any adapters except SQLite.
|
99
|
+
def requires_reloading?
|
100
|
+
false
|
101
|
+
end
|
263
102
|
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
when Time, DateTime then "'#{value.strftime("%Y-%m-%d %H:%M:%S")}'"
|
272
|
-
else "'#{value.to_yaml.gsub(/'/, "''")}'"
|
103
|
+
# Lazily verify this connection, calling +active?+ only if it hasn't
|
104
|
+
# been called for +timeout+ seconds.
|
105
|
+
def verify!(timeout)
|
106
|
+
now = Time.now.to_i
|
107
|
+
if (now - @last_verification) > timeout
|
108
|
+
reconnect! unless active?
|
109
|
+
@last_verification = now
|
273
110
|
end
|
274
111
|
end
|
275
112
|
|
276
|
-
|
277
|
-
|
113
|
+
# Provides access to the underlying database connection. Useful for
|
114
|
+
# when you need to call a proprietary method such as postgresql's lo_*
|
115
|
+
# methods
|
116
|
+
def raw_connection
|
117
|
+
@connection
|
278
118
|
end
|
279
119
|
|
280
|
-
|
281
|
-
|
120
|
+
def log_info(sql, name, runtime)
|
121
|
+
if @logger && @logger.debug?
|
122
|
+
name = "#{name.nil? ? "SQL" : name} (#{sprintf("%f", runtime)})"
|
123
|
+
@logger.debug format_log_entry(name, sql.squeeze(' '))
|
124
|
+
end
|
125
|
+
end
|
282
126
|
|
283
127
|
protected
|
284
|
-
def log(sql, name
|
285
|
-
|
286
|
-
if @logger.
|
287
|
-
action.call(connection)
|
288
|
-
else
|
128
|
+
def log(sql, name)
|
129
|
+
if block_given?
|
130
|
+
if @logger and @logger.debug?
|
289
131
|
result = nil
|
290
|
-
|
291
|
-
@runtime +=
|
292
|
-
log_info(sql, name,
|
132
|
+
seconds = Benchmark.realtime { result = yield }
|
133
|
+
@runtime += seconds
|
134
|
+
log_info(sql, name, seconds)
|
293
135
|
result
|
136
|
+
else
|
137
|
+
yield
|
294
138
|
end
|
295
|
-
|
296
|
-
log_info(
|
297
|
-
|
139
|
+
else
|
140
|
+
log_info(sql, name, 0)
|
141
|
+
nil
|
298
142
|
end
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
sql.gsub(/ +/, " ")
|
308
|
-
)
|
309
|
-
)
|
143
|
+
rescue Exception => e
|
144
|
+
# Log message and raise exception.
|
145
|
+
# Set last_verification to 0, so that connection gets verified
|
146
|
+
# upon reentering the request loop
|
147
|
+
@last_verification = 0
|
148
|
+
message = "#{e.class.name}: #{e.message}: #{sql}"
|
149
|
+
log_info(message, name, 0)
|
150
|
+
raise ActiveRecord::StatementInvalid, message
|
310
151
|
end
|
311
152
|
|
312
153
|
def format_log_entry(message, dump = nil)
|
313
|
-
if
|
314
|
-
@@row_even
|
154
|
+
if ActiveRecord::Base.colorize_logging
|
155
|
+
if @@row_even
|
156
|
+
@@row_even = false
|
157
|
+
message_color, dump_color = "4;36;1", "0;1"
|
158
|
+
else
|
159
|
+
@@row_even = true
|
160
|
+
message_color, dump_color = "4;35;1", "0"
|
161
|
+
end
|
162
|
+
|
163
|
+
log_entry = " \e[#{message_color}m#{message}\e[0m "
|
164
|
+
log_entry << "\e[#{dump_color}m%#{String === dump ? 's' : 'p'}\e[0m" % dump if dump
|
165
|
+
log_entry
|
315
166
|
else
|
316
|
-
|
167
|
+
"%s %s" % [message, dump]
|
317
168
|
end
|
318
|
-
|
319
|
-
log_entry = " \e[#{message_color}m#{message}\e[m"
|
320
|
-
log_entry << " \e[#{dump_color}m%s\e[m" % dump if dump.kind_of?(String) && !dump.nil?
|
321
|
-
log_entry << " \e[#{dump_color}m%p\e[m" % dump if !dump.kind_of?(String) && !dump.nil?
|
322
|
-
log_entry
|
323
169
|
end
|
324
170
|
end
|
325
171
|
end
|