activerecord 2.0.5 → 2.1.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 +168 -6
- data/README +27 -22
- data/RUNNING_UNIT_TESTS +7 -4
- data/Rakefile +22 -25
- data/lib/active_record.rb +8 -2
- data/lib/active_record/aggregations.rb +21 -12
- data/lib/active_record/association_preload.rb +277 -0
- data/lib/active_record/associations.rb +481 -295
- data/lib/active_record/associations/association_collection.rb +162 -37
- data/lib/active_record/associations/association_proxy.rb +71 -7
- data/lib/active_record/associations/belongs_to_association.rb +5 -3
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +5 -6
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +12 -64
- data/lib/active_record/associations/has_many_association.rb +8 -73
- data/lib/active_record/associations/has_many_through_association.rb +68 -117
- data/lib/active_record/associations/has_one_association.rb +7 -5
- data/lib/active_record/associations/has_one_through_association.rb +28 -0
- data/lib/active_record/attribute_methods.rb +69 -19
- data/lib/active_record/base.rb +496 -275
- data/lib/active_record/calculations.rb +28 -21
- data/lib/active_record/callbacks.rb +9 -38
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +3 -2
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +6 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +232 -45
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +141 -27
- data/lib/active_record/connection_adapters/abstract_adapter.rb +9 -13
- data/lib/active_record/connection_adapters/mysql_adapter.rb +57 -24
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +143 -42
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +18 -10
- data/lib/active_record/dirty.rb +158 -0
- data/lib/active_record/fixtures.rb +121 -156
- data/lib/active_record/locking/optimistic.rb +14 -11
- data/lib/active_record/locking/pessimistic.rb +2 -2
- data/lib/active_record/migration.rb +157 -77
- data/lib/active_record/named_scope.rb +163 -0
- data/lib/active_record/observer.rb +19 -5
- data/lib/active_record/reflection.rb +34 -14
- data/lib/active_record/schema.rb +7 -14
- data/lib/active_record/schema_dumper.rb +4 -4
- data/lib/active_record/serialization.rb +5 -5
- data/lib/active_record/serializers/json_serializer.rb +37 -28
- data/lib/active_record/serializers/xml_serializer.rb +52 -29
- data/lib/active_record/test_case.rb +36 -0
- data/lib/active_record/timestamp.rb +4 -4
- data/lib/active_record/transactions.rb +3 -3
- data/lib/active_record/validations.rb +182 -248
- data/lib/active_record/version.rb +2 -2
- data/test/{fixtures → assets}/example.log +0 -0
- data/test/{fixtures → assets}/flowers.jpg +0 -0
- data/test/cases/aaa_create_tables_test.rb +24 -0
- data/test/cases/active_schema_test_mysql.rb +95 -0
- data/test/cases/active_schema_test_postgresql.rb +24 -0
- data/test/{adapter_test.rb → cases/adapter_test.rb} +15 -14
- data/test/{adapter_test_sqlserver.rb → cases/adapter_test_sqlserver.rb} +95 -95
- data/test/{aggregations_test.rb → cases/aggregations_test.rb} +20 -20
- data/test/{ar_schema_test.rb → cases/ar_schema_test.rb} +6 -6
- data/test/cases/associations/belongs_to_associations_test.rb +412 -0
- data/test/{associations → cases/associations}/callbacks_test.rb +24 -10
- data/test/{associations → cases/associations}/cascaded_eager_loading_test.rb +18 -17
- data/test/cases/associations/eager_load_nested_include_test.rb +83 -0
- data/test/{associations → cases/associations}/eager_singularization_test.rb +5 -5
- data/test/{associations → cases/associations}/eager_test.rb +216 -51
- data/test/{associations → cases/associations}/extension_test.rb +8 -8
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +684 -0
- data/test/cases/associations/has_many_associations_test.rb +932 -0
- data/test/cases/associations/has_many_through_associations_test.rb +190 -0
- data/test/cases/associations/has_one_associations_test.rb +323 -0
- data/test/cases/associations/has_one_through_associations_test.rb +74 -0
- data/test/{associations → cases/associations}/inner_join_association_test.rb +20 -20
- data/test/{associations → cases/associations}/join_model_test.rb +175 -35
- data/test/cases/associations_test.rb +262 -0
- data/test/{attribute_methods_test.rb → cases/attribute_methods_test.rb} +103 -11
- data/test/{base_test.rb → cases/base_test.rb} +338 -191
- data/test/{binary_test.rb → cases/binary_test.rb} +6 -4
- data/test/{calculations_test.rb → cases/calculations_test.rb} +35 -23
- data/test/{callbacks_test.rb → cases/callbacks_test.rb} +7 -7
- data/test/{class_inheritable_attributes_test.rb → cases/class_inheritable_attributes_test.rb} +3 -3
- data/test/{column_alias_test.rb → cases/column_alias_test.rb} +3 -3
- data/test/{connection_test_firebird.rb → cases/connection_test_firebird.rb} +2 -2
- data/test/{connection_test_mysql.rb → cases/connection_test_mysql.rb} +2 -2
- data/test/{copy_table_test_sqlite.rb → cases/copy_table_test_sqlite.rb} +13 -13
- data/test/{datatype_test_postgresql.rb → cases/datatype_test_postgresql.rb} +8 -8
- data/test/{date_time_test.rb → cases/date_time_test.rb} +5 -5
- data/test/{default_test_firebird.rb → cases/default_test_firebird.rb} +3 -3
- data/test/{defaults_test.rb → cases/defaults_test.rb} +8 -6
- data/test/{deprecated_finder_test.rb → cases/deprecated_finder_test.rb} +3 -3
- data/test/cases/dirty_test.rb +163 -0
- data/test/cases/finder_respond_to_test.rb +76 -0
- data/test/{finder_test.rb → cases/finder_test.rb} +266 -33
- data/test/{fixtures_test.rb → cases/fixtures_test.rb} +88 -72
- data/test/cases/helper.rb +47 -0
- data/test/{inheritance_test.rb → cases/inheritance_test.rb} +61 -17
- data/test/cases/invalid_date_test.rb +24 -0
- data/test/{json_serialization_test.rb → cases/json_serialization_test.rb} +36 -11
- data/test/{lifecycle_test.rb → cases/lifecycle_test.rb} +16 -13
- data/test/{locking_test.rb → cases/locking_test.rb} +17 -10
- data/test/{method_scoping_test.rb → cases/method_scoping_test.rb} +75 -39
- data/test/{migration_test.rb → cases/migration_test.rb} +420 -80
- data/test/{migration_test_firebird.rb → cases/migration_test_firebird.rb} +3 -3
- data/test/{mixin_test.rb → cases/mixin_test.rb} +7 -6
- data/test/{modules_test.rb → cases/modules_test.rb} +11 -6
- data/test/{multiple_db_test.rb → cases/multiple_db_test.rb} +5 -5
- data/test/cases/named_scope_test.rb +157 -0
- data/test/{pk_test.rb → cases/pk_test.rb} +10 -10
- data/test/{query_cache_test.rb → cases/query_cache_test.rb} +12 -10
- data/test/{readonly_test.rb → cases/readonly_test.rb} +11 -11
- data/test/{reflection_test.rb → cases/reflection_test.rb} +15 -14
- data/test/{reserved_word_test_mysql.rb → cases/reserved_word_test_mysql.rb} +4 -5
- data/test/{schema_authorization_test_postgresql.rb → cases/schema_authorization_test_postgresql.rb} +5 -5
- data/test/cases/schema_dumper_test.rb +138 -0
- data/test/cases/schema_test_postgresql.rb +102 -0
- data/test/{serialization_test.rb → cases/serialization_test.rb} +7 -7
- data/test/{synonym_test_oracle.rb → cases/synonym_test_oracle.rb} +5 -5
- data/test/{table_name_test_sqlserver.rb → cases/table_name_test_sqlserver.rb} +3 -3
- data/test/{threaded_connections_test.rb → cases/threaded_connections_test.rb} +7 -7
- data/test/{transactions_test.rb → cases/transactions_test.rb} +31 -5
- data/test/{unconnected_test.rb → cases/unconnected_test.rb} +2 -2
- data/test/{validations_test.rb → cases/validations_test.rb} +141 -39
- data/test/{xml_serialization_test.rb → cases/xml_serialization_test.rb} +12 -12
- data/test/config.rb +5 -0
- data/test/connections/native_db2/connection.rb +1 -1
- data/test/connections/native_firebird/connection.rb +1 -1
- data/test/connections/native_frontbase/connection.rb +1 -1
- data/test/connections/native_mysql/connection.rb +1 -1
- data/test/connections/native_openbase/connection.rb +1 -1
- data/test/connections/native_oracle/connection.rb +1 -1
- data/test/connections/native_postgresql/connection.rb +1 -3
- data/test/connections/native_sqlite/connection.rb +2 -2
- data/test/connections/native_sqlite3/connection.rb +2 -2
- data/test/connections/native_sqlite3/in_memory_connection.rb +3 -3
- data/test/connections/native_sybase/connection.rb +1 -1
- data/test/fixtures/author_addresses.yml +5 -0
- data/test/fixtures/authors.yml +2 -0
- data/test/fixtures/clubs.yml +6 -0
- data/test/fixtures/jobs.yml +7 -0
- data/test/fixtures/members.yml +4 -0
- data/test/fixtures/memberships.yml +20 -0
- data/test/fixtures/owners.yml +7 -0
- data/test/fixtures/people.yml +4 -1
- data/test/fixtures/pets.yml +14 -0
- data/test/fixtures/posts.yml +1 -0
- data/test/fixtures/price_estimates.yml +7 -0
- data/test/fixtures/readers.yml +5 -0
- data/test/fixtures/references.yml +17 -0
- data/test/fixtures/sponsors.yml +9 -0
- data/test/fixtures/subscribers.yml +7 -0
- data/test/fixtures/subscriptions.yml +12 -0
- data/test/fixtures/taggings.yml +4 -1
- data/test/fixtures/topics.yml +22 -2
- data/test/fixtures/warehouse-things.yml +3 -0
- data/test/{fixtures/migrations_with_decimal → migrations/decimal}/1_give_me_big_numbers.rb +0 -0
- data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/1_people_have_last_names.rb +1 -1
- data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/2_we_need_reminders.rb +1 -1
- data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/3_foo.rb +0 -0
- data/test/{fixtures/migrations → migrations/duplicate}/3_innocent_jointable.rb +0 -0
- data/test/migrations/duplicate_names/20080507052938_chunky.rb +7 -0
- data/test/migrations/duplicate_names/20080507053028_chunky.rb +7 -0
- data/test/{fixtures/migrations_with_duplicate → migrations/interleaved/pass_1}/3_innocent_jointable.rb +0 -0
- data/test/{fixtures/migrations → migrations/interleaved/pass_2}/1_people_have_last_names.rb +1 -1
- data/test/{fixtures/migrations_with_missing_versions/4_innocent_jointable.rb → migrations/interleaved/pass_2/3_innocent_jointable.rb} +0 -0
- data/test/{fixtures/migrations_with_missing_versions → migrations/interleaved/pass_3}/1_people_have_last_names.rb +1 -1
- data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +8 -0
- data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +12 -0
- data/test/{fixtures/migrations_with_missing_versions → migrations/missing}/1000_people_have_middle_names.rb +1 -1
- data/test/migrations/missing/1_people_have_last_names.rb +9 -0
- data/test/{fixtures/migrations_with_missing_versions → migrations/missing}/3_we_need_reminders.rb +1 -1
- data/test/migrations/missing/4_innocent_jointable.rb +12 -0
- data/test/migrations/valid/1_people_have_last_names.rb +9 -0
- data/test/{fixtures/migrations → migrations/valid}/2_we_need_reminders.rb +1 -1
- data/test/migrations/valid/3_innocent_jointable.rb +12 -0
- data/test/{fixtures → models}/author.rb +28 -4
- data/test/{fixtures → models}/auto_id.rb +0 -0
- data/test/{fixtures → models}/binary.rb +0 -0
- data/test/{fixtures → models}/book.rb +0 -0
- data/test/{fixtures → models}/categorization.rb +0 -0
- data/test/{fixtures → models}/category.rb +8 -5
- data/test/{fixtures → models}/citation.rb +0 -0
- data/test/models/club.rb +7 -0
- data/test/{fixtures → models}/column_name.rb +0 -0
- data/test/{fixtures → models}/comment.rb +5 -3
- data/test/{fixtures → models}/company.rb +15 -6
- data/test/{fixtures → models}/company_in_module.rb +5 -3
- data/test/{fixtures → models}/computer.rb +0 -1
- data/test/{fixtures → models}/contact.rb +1 -1
- data/test/{fixtures → models}/course.rb +0 -0
- data/test/{fixtures → models}/customer.rb +8 -8
- data/test/{fixtures → models}/default.rb +0 -0
- data/test/{fixtures → models}/developer.rb +14 -10
- data/test/{fixtures → models}/edge.rb +0 -0
- data/test/{fixtures → models}/entrant.rb +0 -0
- data/test/models/guid.rb +2 -0
- data/test/{fixtures → models}/item.rb +0 -0
- data/test/models/job.rb +5 -0
- data/test/{fixtures → models}/joke.rb +0 -0
- data/test/{fixtures → models}/keyboard.rb +0 -0
- data/test/{fixtures → models}/legacy_thing.rb +0 -0
- data/test/{fixtures → models}/matey.rb +0 -0
- data/test/models/member.rb +9 -0
- data/test/models/membership.rb +9 -0
- data/test/{fixtures → models}/minimalistic.rb +0 -0
- data/test/{fixtures → models}/mixed_case_monkey.rb +0 -0
- data/test/{fixtures → models}/movie.rb +0 -0
- data/test/{fixtures → models}/order.rb +2 -2
- data/test/models/owner.rb +4 -0
- data/test/{fixtures → models}/parrot.rb +0 -0
- data/test/models/person.rb +10 -0
- data/test/models/pet.rb +4 -0
- data/test/models/pirate.rb +9 -0
- data/test/{fixtures → models}/post.rb +23 -2
- data/test/models/price_estimate.rb +3 -0
- data/test/{fixtures → models}/project.rb +1 -0
- data/test/{fixtures → models}/reader.rb +0 -0
- data/test/models/reference.rb +4 -0
- data/test/{fixtures → models}/reply.rb +7 -5
- data/test/{fixtures → models}/ship.rb +0 -0
- data/test/models/sponsor.rb +4 -0
- data/test/{fixtures → models}/subject.rb +0 -0
- data/test/{fixtures → models}/subscriber.rb +2 -0
- data/test/models/subscription.rb +4 -0
- data/test/{fixtures → models}/tag.rb +0 -0
- data/test/{fixtures → models}/tagging.rb +0 -0
- data/test/{fixtures → models}/task.rb +0 -0
- data/test/{fixtures → models}/topic.rb +32 -4
- data/test/{fixtures → models}/treasure.rb +2 -0
- data/test/{fixtures → models}/vertex.rb +0 -0
- data/test/models/warehouse_thing.rb +5 -0
- data/test/schema/mysql_specific_schema.rb +12 -0
- data/test/schema/postgresql_specific_schema.rb +103 -0
- data/test/schema/schema.rb +421 -0
- data/test/schema/schema2.rb +6 -0
- data/test/schema/sqlite_specific_schema.rb +25 -0
- data/test/schema/sqlserver_specific_schema.rb +5 -0
- metadata +192 -176
- data/test/aaa_create_tables_test.rb +0 -72
- data/test/abstract_unit.rb +0 -84
- data/test/active_schema_test_mysql.rb +0 -46
- data/test/all.sh +0 -8
- data/test/association_inheritance_reload.rb +0 -14
- data/test/associations_test.rb +0 -2177
- data/test/fixtures/bad_fixtures/attr_with_numeric_first_char +0 -1
- data/test/fixtures/bad_fixtures/attr_with_spaces +0 -1
- data/test/fixtures/bad_fixtures/blank_line +0 -3
- data/test/fixtures/bad_fixtures/duplicate_attributes +0 -3
- data/test/fixtures/bad_fixtures/missing_value +0 -1
- data/test/fixtures/db_definitions/db2.drop.sql +0 -33
- data/test/fixtures/db_definitions/db2.sql +0 -235
- data/test/fixtures/db_definitions/db22.drop.sql +0 -2
- data/test/fixtures/db_definitions/db22.sql +0 -5
- data/test/fixtures/db_definitions/firebird.drop.sql +0 -65
- data/test/fixtures/db_definitions/firebird.sql +0 -310
- data/test/fixtures/db_definitions/firebird2.drop.sql +0 -2
- data/test/fixtures/db_definitions/firebird2.sql +0 -6
- data/test/fixtures/db_definitions/frontbase.drop.sql +0 -33
- data/test/fixtures/db_definitions/frontbase.sql +0 -273
- data/test/fixtures/db_definitions/frontbase2.drop.sql +0 -1
- data/test/fixtures/db_definitions/frontbase2.sql +0 -4
- data/test/fixtures/db_definitions/openbase.drop.sql +0 -2
- data/test/fixtures/db_definitions/openbase.sql +0 -318
- data/test/fixtures/db_definitions/openbase2.drop.sql +0 -2
- data/test/fixtures/db_definitions/openbase2.sql +0 -7
- data/test/fixtures/db_definitions/oracle.drop.sql +0 -67
- data/test/fixtures/db_definitions/oracle.sql +0 -330
- data/test/fixtures/db_definitions/oracle2.drop.sql +0 -2
- data/test/fixtures/db_definitions/oracle2.sql +0 -6
- data/test/fixtures/db_definitions/postgresql.drop.sql +0 -44
- data/test/fixtures/db_definitions/postgresql.sql +0 -292
- data/test/fixtures/db_definitions/postgresql2.drop.sql +0 -2
- data/test/fixtures/db_definitions/postgresql2.sql +0 -4
- data/test/fixtures/db_definitions/schema.rb +0 -354
- data/test/fixtures/db_definitions/schema2.rb +0 -11
- data/test/fixtures/db_definitions/sqlite.drop.sql +0 -33
- data/test/fixtures/db_definitions/sqlite.sql +0 -219
- data/test/fixtures/db_definitions/sqlite2.drop.sql +0 -2
- data/test/fixtures/db_definitions/sqlite2.sql +0 -5
- data/test/fixtures/db_definitions/sybase.drop.sql +0 -35
- data/test/fixtures/db_definitions/sybase.sql +0 -222
- data/test/fixtures/db_definitions/sybase2.drop.sql +0 -4
- data/test/fixtures/db_definitions/sybase2.sql +0 -5
- data/test/fixtures/developers_projects/david_action_controller +0 -3
- data/test/fixtures/developers_projects/david_active_record +0 -3
- data/test/fixtures/developers_projects/jamis_active_record +0 -2
- data/test/fixtures/person.rb +0 -4
- data/test/fixtures/pirate.rb +0 -5
- data/test/fixtures/subscribers/first +0 -2
- data/test/fixtures/subscribers/second +0 -2
- data/test/schema_dumper_test.rb +0 -131
- data/test/schema_test_postgresql.rb +0 -64
@@ -13,13 +13,17 @@ module ActiveRecord
|
|
13
13
|
255
|
14
14
|
end
|
15
15
|
|
16
|
-
# Truncates a table alias according to the limits of the current adapter.
|
16
|
+
# Truncates a table alias according to the limits of the current adapter.
|
17
17
|
def table_alias_for(table_name)
|
18
18
|
table_name[0..table_alias_length-1].gsub(/\./, '_')
|
19
19
|
end
|
20
20
|
|
21
21
|
# def tables(name = nil) end
|
22
22
|
|
23
|
+
def table_exists?(table_name)
|
24
|
+
tables.include?(table_name.to_s)
|
25
|
+
end
|
26
|
+
|
23
27
|
# Returns an array of indexes for the given table.
|
24
28
|
# def indexes(table_name, name = nil) end
|
25
29
|
|
@@ -28,7 +32,7 @@ module ActiveRecord
|
|
28
32
|
def columns(table_name, name = nil) end
|
29
33
|
|
30
34
|
# Creates a new table
|
31
|
-
# There are two ways to work with
|
35
|
+
# There are two ways to work with +create_table+. You can use the block
|
32
36
|
# form or the regular form, like this:
|
33
37
|
#
|
34
38
|
# === Block form
|
@@ -45,7 +49,7 @@ module ActiveRecord
|
|
45
49
|
# The +options+ hash can include the following keys:
|
46
50
|
# [<tt>:id</tt>]
|
47
51
|
# Whether to automatically add a primary key column. Defaults to true.
|
48
|
-
# Join tables for has_and_belongs_to_many should set
|
52
|
+
# Join tables for +has_and_belongs_to_many+ should set <tt>:id => false</tt>.
|
49
53
|
# [<tt>:primary_key</tt>]
|
50
54
|
# The name of the primary key, if one is to be added automatically.
|
51
55
|
# Defaults to +id+.
|
@@ -93,8 +97,8 @@ module ActiveRecord
|
|
93
97
|
|
94
98
|
yield table_definition
|
95
99
|
|
96
|
-
if options[:force]
|
97
|
-
drop_table(table_name, options)
|
100
|
+
if options[:force] && table_exists?(table_name)
|
101
|
+
drop_table(table_name, options)
|
98
102
|
end
|
99
103
|
|
100
104
|
create_sql = "CREATE#{' TEMPORARY' if options[:temporary]} TABLE "
|
@@ -104,6 +108,67 @@ module ActiveRecord
|
|
104
108
|
execute create_sql
|
105
109
|
end
|
106
110
|
|
111
|
+
# A block for changing columns in +table+.
|
112
|
+
#
|
113
|
+
# === Example
|
114
|
+
# # change_table() yields a Table instance
|
115
|
+
# change_table(:suppliers) do |t|
|
116
|
+
# t.column :name, :string, :limit => 60
|
117
|
+
# # Other column alterations here
|
118
|
+
# end
|
119
|
+
#
|
120
|
+
# ===== Examples
|
121
|
+
# ====== Add a column
|
122
|
+
# change_table(:suppliers) do |t|
|
123
|
+
# t.column :name, :string, :limit => 60
|
124
|
+
# end
|
125
|
+
#
|
126
|
+
# ====== Add 2 integer columns
|
127
|
+
# change_table(:suppliers) do |t|
|
128
|
+
# t.integer :width, :height, :null => false, :default => 0
|
129
|
+
# end
|
130
|
+
#
|
131
|
+
# ====== Add created_at/updated_at columns
|
132
|
+
# change_table(:suppliers) do |t|
|
133
|
+
# t.timestamps
|
134
|
+
# end
|
135
|
+
#
|
136
|
+
# ====== Add a foreign key column
|
137
|
+
# change_table(:suppliers) do |t|
|
138
|
+
# t.references :company
|
139
|
+
# end
|
140
|
+
#
|
141
|
+
# Creates a <tt>company_id(integer)</tt> column
|
142
|
+
#
|
143
|
+
# ====== Add a polymorphic foreign key column
|
144
|
+
# change_table(:suppliers) do |t|
|
145
|
+
# t.belongs_to :company, :polymorphic => true
|
146
|
+
# end
|
147
|
+
#
|
148
|
+
# Creates <tt>company_type(varchar)</tt> and <tt>company_id(integer)</tt> columns
|
149
|
+
#
|
150
|
+
# ====== Remove a column
|
151
|
+
# change_table(:suppliers) do |t|
|
152
|
+
# t.remove :company
|
153
|
+
# end
|
154
|
+
#
|
155
|
+
# ====== Remove several columns
|
156
|
+
# change_table(:suppliers) do |t|
|
157
|
+
# t.remove :company_id
|
158
|
+
# t.remove :width, :height
|
159
|
+
# end
|
160
|
+
#
|
161
|
+
# ====== Remove an index
|
162
|
+
# change_table(:suppliers) do |t|
|
163
|
+
# t.remove_index :company_id
|
164
|
+
# end
|
165
|
+
#
|
166
|
+
# See also Table for details on
|
167
|
+
# all of the various column transformation
|
168
|
+
def change_table(table_name)
|
169
|
+
yield Table.new(table_name, self)
|
170
|
+
end
|
171
|
+
|
107
172
|
# Renames a table.
|
108
173
|
# ===== Example
|
109
174
|
# rename_table('octopuses', 'octopi')
|
@@ -124,12 +189,16 @@ module ActiveRecord
|
|
124
189
|
execute(add_column_sql)
|
125
190
|
end
|
126
191
|
|
127
|
-
# Removes the column from the table definition.
|
192
|
+
# Removes the column(s) from the table definition.
|
128
193
|
# ===== Examples
|
129
194
|
# remove_column(:suppliers, :qualification)
|
130
|
-
|
131
|
-
|
195
|
+
# remove_columns(:suppliers, :qualification, :experience)
|
196
|
+
def remove_column(table_name, *column_names)
|
197
|
+
column_names.flatten.each do |column_name|
|
198
|
+
execute "ALTER TABLE #{quote_table_name(table_name)} DROP #{quote_column_name(column_name)}"
|
199
|
+
end
|
132
200
|
end
|
201
|
+
alias :remove_columns :remove_column
|
133
202
|
|
134
203
|
# Changes the column's definition according to the new options.
|
135
204
|
# See TableDefinition#column for details of the options you can use.
|
@@ -161,12 +230,12 @@ module ActiveRecord
|
|
161
230
|
# an Array of Symbols.
|
162
231
|
#
|
163
232
|
# The index will be named after the table and the first column name,
|
164
|
-
# unless you pass
|
233
|
+
# unless you pass <tt>:name</tt> as an option.
|
165
234
|
#
|
166
235
|
# When creating an index on multiple columns, the first column is used as a name
|
167
236
|
# for the index. For example, when you specify an index on two columns
|
168
|
-
# [
|
169
|
-
# index for the first column
|
237
|
+
# [<tt>:first</tt>, <tt>:last</tt>], the DBMS creates an index for both columns as well as an
|
238
|
+
# index for the first column <tt>:first</tt>. Using just the first name for this index
|
170
239
|
# makes sense, because you will never have to create a singular index with this
|
171
240
|
# name.
|
172
241
|
#
|
@@ -230,27 +299,49 @@ module ActiveRecord
|
|
230
299
|
def structure_dump
|
231
300
|
end
|
232
301
|
|
302
|
+
def dump_schema_information #:nodoc:
|
303
|
+
sm_table = ActiveRecord::Migrator.schema_migrations_table_name
|
304
|
+
migrated = select_values("SELECT version FROM #{sm_table}")
|
305
|
+
migrated.map { |v| "INSERT INTO #{sm_table} (version) VALUES ('#{v}');" }.join("\n\n")
|
306
|
+
end
|
307
|
+
|
233
308
|
# Should not be called normally, but this operation is non-destructive.
|
234
309
|
# The migrations module handles this automatically.
|
235
|
-
def
|
236
|
-
|
237
|
-
execute "CREATE TABLE #{quote_table_name(ActiveRecord::Migrator.schema_info_table_name)} (version #{type_to_sql(:integer)})"
|
238
|
-
execute "INSERT INTO #{quote_table_name(ActiveRecord::Migrator.schema_info_table_name)} (version) VALUES(0)"
|
239
|
-
rescue ActiveRecord::StatementInvalid
|
240
|
-
# Schema has been initialized
|
241
|
-
end
|
242
|
-
end
|
310
|
+
def initialize_schema_migrations_table
|
311
|
+
sm_table = ActiveRecord::Migrator.schema_migrations_table_name
|
243
312
|
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
313
|
+
unless tables.detect { |t| t == sm_table }
|
314
|
+
create_table(sm_table, :id => false) do |schema_migrations_table|
|
315
|
+
schema_migrations_table.column :version, :string, :null => false
|
316
|
+
end
|
317
|
+
add_index sm_table, :version, :unique => true,
|
318
|
+
:name => 'unique_schema_migrations'
|
319
|
+
|
320
|
+
# Backwards-compatibility: if we find schema_info, assume we've
|
321
|
+
# migrated up to that point:
|
322
|
+
si_table = Base.table_name_prefix + 'schema_info' + Base.table_name_suffix
|
323
|
+
|
324
|
+
if tables.detect { |t| t == si_table }
|
325
|
+
|
326
|
+
old_version = select_value("SELECT version FROM #{quote_table_name(si_table)}").to_i
|
327
|
+
assume_migrated_upto_version(old_version)
|
328
|
+
drop_table(si_table)
|
248
329
|
end
|
249
|
-
rescue ActiveRecord::StatementInvalid
|
250
|
-
# No Schema Info
|
251
330
|
end
|
252
331
|
end
|
253
332
|
|
333
|
+
def assume_migrated_upto_version(version)
|
334
|
+
sm_table = quote_table_name(ActiveRecord::Migrator.schema_migrations_table_name)
|
335
|
+
migrated = select_values("SELECT version FROM #{sm_table}").map(&:to_i)
|
336
|
+
versions = Dir['db/migrate/[0-9]*_*.rb'].map do |filename|
|
337
|
+
filename.split('/').last.split('_').first.to_i
|
338
|
+
end
|
339
|
+
|
340
|
+
execute "INSERT INTO #{sm_table} (version) VALUES ('#{version}')" unless migrated.include?(version.to_i)
|
341
|
+
(versions - migrated).select { |v| v < version.to_i }.each do |v|
|
342
|
+
execute "INSERT INTO #{sm_table} (version) VALUES ('#{v}')"
|
343
|
+
end
|
344
|
+
end
|
254
345
|
|
255
346
|
def type_to_sql(type, limit = nil, precision = nil, scale = nil) #:nodoc:
|
256
347
|
if native = native_database_types[type]
|
@@ -281,7 +372,14 @@ module ActiveRecord
|
|
281
372
|
|
282
373
|
def add_column_options!(sql, options) #:nodoc:
|
283
374
|
sql << " DEFAULT #{quote(options[:default], options[:column])}" if options_include_default?(options)
|
284
|
-
|
375
|
+
# must explcitly check for :null to allow change_column to work on migrations
|
376
|
+
if options.has_key? :null
|
377
|
+
if options[:null] == false
|
378
|
+
sql << " NOT NULL"
|
379
|
+
else
|
380
|
+
sql << " NULL"
|
381
|
+
end
|
382
|
+
end
|
285
383
|
end
|
286
384
|
|
287
385
|
# SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause.
|
@@ -291,13 +389,29 @@ module ActiveRecord
|
|
291
389
|
def distinct(columns, order_by)
|
292
390
|
"DISTINCT #{columns}"
|
293
391
|
end
|
294
|
-
|
392
|
+
|
295
393
|
# ORDER BY clause for the passed order option.
|
296
394
|
# PostgreSQL overrides this due to its stricter standards compliance.
|
297
395
|
def add_order_by_for_association_limiting!(sql, options)
|
298
396
|
sql << " ORDER BY #{options[:order]}"
|
299
397
|
end
|
300
398
|
|
399
|
+
# Adds timestamps (created_at and updated_at) columns to the named table.
|
400
|
+
# ===== Examples
|
401
|
+
# add_timestamps(:suppliers)
|
402
|
+
def add_timestamps(table_name)
|
403
|
+
add_column table_name, :created_at, :datetime
|
404
|
+
add_column table_name, :updated_at, :datetime
|
405
|
+
end
|
406
|
+
|
407
|
+
# Removes the timestamp columns (created_at and updated_at) from the table definition.
|
408
|
+
# ===== Examples
|
409
|
+
# remove_timestamps(:suppliers)
|
410
|
+
def remove_timestamps(table_name)
|
411
|
+
remove_column table_name, :updated_at
|
412
|
+
remove_column table_name, :created_at
|
413
|
+
end
|
414
|
+
|
301
415
|
protected
|
302
416
|
def options_include_default?(options)
|
303
417
|
options.include?(:default) && !(options[:null] == false && options[:default].nil?)
|
@@ -66,14 +66,14 @@ module ActiveRecord
|
|
66
66
|
|
67
67
|
# QUOTING ==================================================
|
68
68
|
|
69
|
-
# Override to return the quoted table name
|
69
|
+
# Override to return the quoted table name. Defaults to column quoting.
|
70
70
|
def quote_table_name(name)
|
71
|
-
name
|
71
|
+
quote_column_name(name)
|
72
72
|
end
|
73
73
|
|
74
74
|
# REFERENTIAL INTEGRITY ====================================
|
75
75
|
|
76
|
-
# Override to turn off referential integrity while executing
|
76
|
+
# Override to turn off referential integrity while executing <tt>&block</tt>.
|
77
77
|
def disable_referential_integrity(&block)
|
78
78
|
yield
|
79
79
|
end
|
@@ -101,7 +101,7 @@ module ActiveRecord
|
|
101
101
|
false
|
102
102
|
end
|
103
103
|
|
104
|
-
# Lazily verify this connection, calling
|
104
|
+
# Lazily verify this connection, calling <tt>active?</tt> only if it hasn't
|
105
105
|
# been called for +timeout+ seconds.
|
106
106
|
def verify!(timeout)
|
107
107
|
now = Time.now.to_i
|
@@ -128,15 +128,11 @@ module ActiveRecord
|
|
128
128
|
protected
|
129
129
|
def log(sql, name)
|
130
130
|
if block_given?
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
result
|
137
|
-
else
|
138
|
-
yield
|
139
|
-
end
|
131
|
+
result = nil
|
132
|
+
seconds = Benchmark.realtime { result = yield }
|
133
|
+
@runtime += seconds
|
134
|
+
log_info(sql, name, seconds)
|
135
|
+
result
|
140
136
|
else
|
141
137
|
log_info(sql, name, 0)
|
142
138
|
nil
|
@@ -94,7 +94,7 @@ module ActiveRecord
|
|
94
94
|
def extract_default(default)
|
95
95
|
if type == :binary || type == :text
|
96
96
|
if default.blank?
|
97
|
-
|
97
|
+
nil
|
98
98
|
else
|
99
99
|
raise ArgumentError, "#{type} columns cannot have a default value: #{default.inspect}"
|
100
100
|
end
|
@@ -112,6 +112,23 @@ module ActiveRecord
|
|
112
112
|
super
|
113
113
|
end
|
114
114
|
|
115
|
+
def extract_limit(sql_type)
|
116
|
+
if sql_type =~ /blob|text/i
|
117
|
+
case sql_type
|
118
|
+
when /tiny/i
|
119
|
+
255
|
120
|
+
when /medium/i
|
121
|
+
16777215
|
122
|
+
when /long/i
|
123
|
+
2147483647 # mysql only allows 2^31-1, not 2^32-1, somewhat inconsistently with the tiny/medium/normal cases
|
124
|
+
else
|
125
|
+
super # we could return 65535 here, but we leave it undecorated by default
|
126
|
+
end
|
127
|
+
else
|
128
|
+
super
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
115
132
|
# MySQL misreports NOT NULL column default when none is given.
|
116
133
|
# We can't detect this for columns which may have a legitimate ''
|
117
134
|
# default (string) but we can for others (integer, datetime, boolean,
|
@@ -129,19 +146,19 @@ module ActiveRecord
|
|
129
146
|
#
|
130
147
|
# Options:
|
131
148
|
#
|
132
|
-
# * <tt>:host</tt>
|
133
|
-
# * <tt>:port</tt>
|
134
|
-
# * <tt>:socket</tt>
|
135
|
-
# * <tt>:username</tt>
|
136
|
-
# * <tt>:password</tt>
|
137
|
-
# * <tt>:database</tt>
|
138
|
-
# * <tt>:encoding</tt>
|
139
|
-
# * <tt>:sslkey</tt>
|
140
|
-
# * <tt>:sslcert</tt>
|
141
|
-
# * <tt>:sslcapath</tt>
|
142
|
-
# * <tt>:sslcipher</tt>
|
149
|
+
# * <tt>:host</tt> - Defaults to "localhost".
|
150
|
+
# * <tt>:port</tt> - Defaults to 3306.
|
151
|
+
# * <tt>:socket</tt> - Defaults to "/tmp/mysql.sock".
|
152
|
+
# * <tt>:username</tt> - Defaults to "root"
|
153
|
+
# * <tt>:password</tt> - Defaults to nothing.
|
154
|
+
# * <tt>:database</tt> - The name of the database. No default, must be provided.
|
155
|
+
# * <tt>:encoding</tt> - (Optional) Sets the client encoding by executing "SET NAMES <encoding>" after connection.
|
156
|
+
# * <tt>:sslkey</tt> - Necessary to use MySQL with an SSL connection.
|
157
|
+
# * <tt>:sslcert</tt> - Necessary to use MySQL with an SSL connection.
|
158
|
+
# * <tt>:sslcapath</tt> - Necessary to use MySQL with an SSL connection.
|
159
|
+
# * <tt>:sslcipher</tt> - Necessary to use MySQL with an SSL connection.
|
143
160
|
#
|
144
|
-
# By default, the MysqlAdapter will consider all columns of type tinyint(1)
|
161
|
+
# By default, the MysqlAdapter will consider all columns of type <tt>tinyint(1)</tt>
|
145
162
|
# as boolean. If you wish to disable this emulation (which was the default
|
146
163
|
# behavior in versions 0.13.1 and earlier) you can add the following line
|
147
164
|
# to your environment.rb file:
|
@@ -155,13 +172,14 @@ module ActiveRecord
|
|
155
172
|
"Server shutdown in progress",
|
156
173
|
"Broken pipe",
|
157
174
|
"Lost connection to MySQL server during query",
|
158
|
-
"MySQL server has gone away"
|
159
|
-
|
175
|
+
"MySQL server has gone away" ]
|
176
|
+
|
177
|
+
QUOTED_TRUE, QUOTED_FALSE = '1', '0'
|
160
178
|
|
161
179
|
def initialize(connection, logger, connection_options, config)
|
162
180
|
super(connection, logger)
|
163
181
|
@connection_options, @config = connection_options, config
|
164
|
-
|
182
|
+
@quoted_column_names, @quoted_table_names = {}, {}
|
165
183
|
connect
|
166
184
|
end
|
167
185
|
|
@@ -178,7 +196,7 @@ module ActiveRecord
|
|
178
196
|
:primary_key => "int(11) DEFAULT NULL auto_increment PRIMARY KEY",
|
179
197
|
:string => { :name => "varchar", :limit => 255 },
|
180
198
|
:text => { :name => "text" },
|
181
|
-
:integer => { :name => "int"
|
199
|
+
:integer => { :name => "int"},
|
182
200
|
:float => { :name => "float" },
|
183
201
|
:decimal => { :name => "decimal" },
|
184
202
|
:datetime => { :name => "datetime" },
|
@@ -205,11 +223,11 @@ module ActiveRecord
|
|
205
223
|
end
|
206
224
|
|
207
225
|
def quote_column_name(name) #:nodoc:
|
208
|
-
"`#{name}`"
|
226
|
+
@quoted_column_names[name] ||= "`#{name}`"
|
209
227
|
end
|
210
228
|
|
211
229
|
def quote_table_name(name) #:nodoc:
|
212
|
-
quote_column_name(name).gsub('.', '`.`')
|
230
|
+
@quoted_table_names[name] ||= quote_column_name(name).gsub('.', '`.`')
|
213
231
|
end
|
214
232
|
|
215
233
|
def quote_string(string) #:nodoc:
|
@@ -217,11 +235,11 @@ module ActiveRecord
|
|
217
235
|
end
|
218
236
|
|
219
237
|
def quoted_true
|
220
|
-
|
238
|
+
QUOTED_TRUE
|
221
239
|
end
|
222
240
|
|
223
241
|
def quoted_false
|
224
|
-
|
242
|
+
QUOTED_FALSE
|
225
243
|
end
|
226
244
|
|
227
245
|
# REFERENTIAL INTEGRITY ====================================
|
@@ -318,11 +336,10 @@ module ActiveRecord
|
|
318
336
|
|
319
337
|
def add_limit_offset!(sql, options) #:nodoc:
|
320
338
|
if limit = options[:limit]
|
321
|
-
limit = sanitize_limit(limit)
|
322
339
|
unless offset = options[:offset]
|
323
340
|
sql << " LIMIT #{limit}"
|
324
341
|
else
|
325
|
-
sql << " LIMIT #{offset
|
342
|
+
sql << " LIMIT #{offset}, #{limit}"
|
326
343
|
end
|
327
344
|
end
|
328
345
|
end
|
@@ -348,7 +365,7 @@ module ActiveRecord
|
|
348
365
|
create_database(name)
|
349
366
|
end
|
350
367
|
|
351
|
-
# Create a new MySQL database with optional
|
368
|
+
# Create a new MySQL database with optional <tt>:charset</tt> and <tt>:collation</tt>.
|
352
369
|
# Charset defaults to utf8.
|
353
370
|
#
|
354
371
|
# Example:
|
@@ -446,6 +463,22 @@ module ActiveRecord
|
|
446
463
|
execute "ALTER TABLE #{quote_table_name(table_name)} CHANGE #{quote_column_name(column_name)} #{quote_column_name(new_column_name)} #{current_type}"
|
447
464
|
end
|
448
465
|
|
466
|
+
# Maps logical Rails types to MySQL-specific data types.
|
467
|
+
def type_to_sql(type, limit = nil, precision = nil, scale = nil)
|
468
|
+
return super unless type.to_s == 'integer'
|
469
|
+
|
470
|
+
case limit
|
471
|
+
when 0..3
|
472
|
+
"smallint(#{limit})"
|
473
|
+
when 4..8
|
474
|
+
"int(#{limit})"
|
475
|
+
when 9..20
|
476
|
+
"bigint(#{limit})"
|
477
|
+
else
|
478
|
+
'int(11)'
|
479
|
+
end
|
480
|
+
end
|
481
|
+
|
449
482
|
|
450
483
|
# SHOW VARIABLES LIKE 'name'
|
451
484
|
def show_variable(name)
|