Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 599 lines (537 sloc) 24.046 kb
86dda36 @jeremy Avoid deprecated String#to_a by using Array.wrap(...) instead of Array(....
jeremy authored
1 require 'active_support/core_ext/array/wrap'
bb95e81 @tenderlove Adding a deprecation warning for use of the schema_info table.
tenderlove authored
2 require 'active_support/deprecation/reporting'
86dda36 @jeremy Avoid deprecated String#to_a by using Array.wrap(...) instead of Array(....
jeremy authored
3
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
4 module ActiveRecord
5 module ConnectionAdapters # :nodoc:
6 module SchemaStatements
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
7 # Returns a Hash of mappings from the abstract data types to the native
0034b78 @smartinez87 Remove extra white spaces on ActiveRecord docs.
smartinez87 authored
8 # database types. See TableDefinition#column for details on the recognized
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
9 # abstract data types.
10 def native_database_types
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
11 {}
12 end
13
46f30f9 @lifo Merge documentation changes from docrails.
lifo authored
14 # Truncates a table alias according to the limits of the current adapter.
229c0f4 @technoweenie Rework table aliasing to account for truncated table aliases. Add smart...
technoweenie authored
15 def table_alias_for(table_name)
59ec131 @tenderlove move ivar to initialize, use triple dot rather than minus
tenderlove authored
16 table_name[0...table_alias_length].gsub(/\./, '_')
263479b @technoweenie Add AbstractAdapter#table_alias_for to create table aliases according to...
technoweenie authored
17 end
18
616eef3 @smartinez87 Added doc for #table_exists?
smartinez87 authored
19 # Checks to see if the table +table_name+ exists on the database.
20 #
21 # === Example
22 # table_exists?(:developers)
8877ab5 @tarmo Added AbstractAdapter#table_exists? and made AbstractAdapter#table imple...
tarmo authored
23 def table_exists?(table_name)
38703ac @jonleighton Revert naive O(1) table_exists? implementation.
jonleighton authored
24 tables.include?(table_name.to_s)
8877ab5 @tarmo Added AbstractAdapter#table_exists? and made AbstractAdapter#table imple...
tarmo authored
25 end
26
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
27 # Returns an array of indexes for the given table.
28 # def indexes(table_name, name = nil) end
29
0ce94f4 @smartinez87 dot missing here
smartinez87 authored
30 # Checks to see if an index exists on a table for a given index definition.
11ff3da @pixeltrix Add column and index query methods to ActiveRecord::Schema
pixeltrix authored
31 #
32 # === Examples
33 # # Check an index exists
34 # index_exists?(:suppliers, :company_id)
35 #
36 # # Check an index on multiple columns exists
37 # index_exists?(:suppliers, [:company_id, :company_type])
38 #
39 # # Check a unique index exists
40 # index_exists?(:suppliers, :company_id, :unique => true)
41 #
42 # # Check an index with a custom name exists
43 # index_exists?(:suppliers, :company_id, :name => "idx_company_id"
44 def index_exists?(table_name, column_name, options = {})
45 column_names = Array.wrap(column_name)
46 index_name = options.key?(:name) ? options[:name].to_s : index_name(table_name, :column => column_names)
47 if options[:unique]
48 indexes(table_name).any?{ |i| i.unique && i.name == index_name }
49 else
50 indexes(table_name).any?{ |i| i.name == index_name }
51 end
52 end
53
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
54 # Returns an array of Column objects for the table specified by +table_name+.
55 # See the concrete implementation for details on the expected parameter values.
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
56 def columns(table_name, name = nil) end
57
11ff3da @pixeltrix Add column and index query methods to ActiveRecord::Schema
pixeltrix authored
58 # Checks to see if a column exists in a given table.
59 #
60 # === Examples
61 # # Check a column exists
62 # column_exists?(:suppliers, :name)
63 #
64 # # Check a column exists of a particular type
65 # column_exists?(:suppliers, :name, :string)
66 #
67 # # Check a column exists with a specific definition
68 # column_exists?(:suppliers, :name, :string, :limit => 100)
8f358f3 @spastorino Refactor of column_exists? method and this works with PostgreSQL
spastorino authored
69 def column_exists?(table_name, column_name, type = nil, options = {})
70 columns(table_name).any?{ |c| c.name == column_name.to_s &&
71 (!type || c.type == type) &&
72 (!options[:limit] || c.limit == options[:limit]) &&
73 (!options[:precision] || c.precision == options[:precision]) &&
74 (!options[:scale] || c.scale == options[:scale]) }
11ff3da @pixeltrix Add column and index query methods to ActiveRecord::Schema
pixeltrix authored
75 end
76
a293278 @lifo Merge docrails
lifo authored
77 # Creates a new table with the name +table_name+. +table_name+ may either
78 # be a String or a Symbol.
79 #
0034b78 @smartinez87 Remove extra white spaces on ActiveRecord docs.
smartinez87 authored
80 # There are two ways to work with +create_table+. You can use the block
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
81 # form or the regular form, like this:
82 #
83 # === Block form
a293278 @lifo Merge docrails
lifo authored
84 # # create_table() passes a TableDefinition object to the block.
85 # # This form will not only create the table, but also columns for the
86 # # table.
e033b5d @lifo Merge docrails
lifo authored
87 #
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
88 # create_table(:suppliers) do |t|
89 # t.column :name, :string, :limit => 60
90 # # Other fields here
91 # end
92 #
e033b5d @lifo Merge docrails
lifo authored
93 # === Block form, with shorthand
94 # # You can also use the column types as method calls, rather than calling the column method.
95 # create_table(:suppliers) do |t|
96 # t.string :name, :limit => 60
97 # # Other fields here
98 # end
99 #
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
100 # === Regular form
a293278 @lifo Merge docrails
lifo authored
101 # # Creates a table called 'suppliers' with no columns.
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
102 # create_table(:suppliers)
a293278 @lifo Merge docrails
lifo authored
103 # # Add a column to 'suppliers'.
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
104 # add_column(:suppliers, :name, :string, {:limit => 60})
105 #
106 # The +options+ hash can include the following keys:
107 # [<tt>:id</tt>]
35f7cc2 @jeremy create_table rdoc: suggest :id => false for habtm join tables
jeremy authored
108 # Whether to automatically add a primary key column. Defaults to true.
a958793 @fxn copy-edits some docs
fxn authored
109 # Join tables for +has_and_belongs_to_many+ should set it to false.
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
110 # [<tt>:primary_key</tt>]
111 # The name of the primary key, if one is to be added automatically.
a958793 @fxn copy-edits some docs
fxn authored
112 # Defaults to +id+. If <tt>:id</tt> is false this option is ignored.
f6fa6cf @neerajdotname clarifying how to create non standard primary key
neerajdotname authored
113 #
a958793 @fxn copy-edits some docs
fxn authored
114 # Also note that this just sets the primary key in the table. You additionally
1a474cc @jonleighton Deprecate set_primary_key in favour of self.primary_key=
jonleighton authored
115 # need to configure the primary key in the model via +self.primary_key=+.
b451de0 @spastorino Deletes trailing whitespaces (over text files only find * -type f -exec ...
spastorino authored
116 # Models do NOT auto-detect the primary key from their table definition.
117 #
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
118 # [<tt>:options</tt>]
119 # Any extra options you want appended to the table definition.
120 # [<tt>:temporary</tt>]
121 # Make a temporary table.
fd66ccb @jeremy Document :force option to create_table. References #2921.
jeremy authored
122 # [<tt>:force</tt>]
7143d80 Smattering of grammatical fixes to documentation. Closes #10083 [BobSilv...
Marcel Molina authored
123 # Set to true to drop the table before creating it.
fd66ccb @jeremy Document :force option to create_table. References #2921.
jeremy authored
124 # Defaults to false.
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
125 #
126 # ===== Examples
127 # ====== Add a backend specific option to the generated SQL (MySQL)
128 # create_table(:suppliers, :options => 'ENGINE=InnoDB DEFAULT CHARSET=utf8')
129 # generates:
130 # CREATE TABLE suppliers (
131 # id int(11) DEFAULT NULL auto_increment PRIMARY KEY
132 # ) ENGINE=InnoDB DEFAULT CHARSET=utf8
133 #
134 # ====== Rename the primary key column
135 # create_table(:objects, :primary_key => 'guid') do |t|
136 # t.column :name, :string, :limit => 80
137 # end
138 # generates:
139 # CREATE TABLE objects (
140 # guid int(11) DEFAULT NULL auto_increment PRIMARY KEY,
141 # name varchar(80)
142 # )
143 #
144 # ====== Do not add a primary key column
145 # create_table(:categories_suppliers, :id => false) do |t|
146 # t.column :category_id, :integer
147 # t.column :supplier_id, :integer
148 # end
149 # generates:
e7ed4c9 @jeremy Fix join table docs error in schema_statements. Closes #9880 [lawrence]
jeremy authored
150 # CREATE TABLE categories_suppliers (
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
151 # category_id int,
152 # supplier_id int
153 # )
154 #
155 # See also TableDefinition#column for details on how to create columns.
a2f14e2 @tenderlove Revert "Merge pull request #1163 from amatsuda/sexier_migration_31"
tenderlove authored
156 def create_table(table_name, options = {})
b297911 @tenderlove use inheritence to deal with custom methods
tenderlove authored
157 td = table_definition
158 td.primary_key(options[:primary_key] || Base.get_primary_key(table_name.to_s.singularize)) unless options[:id] == false
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
159
a2f14e2 @tenderlove Revert "Merge pull request #1163 from amatsuda/sexier_migration_31"
tenderlove authored
160 yield td if block_given?
0639e1c @dhh Added :force option to create_table that'll try to drop the table if it ...
dhh authored
161
0a21193 @tarmo create_table :force => true no longer tries to drop a non-existing table
tarmo authored
162 if options[:force] && table_exists?(table_name)
663904f @rafaelfranca Revert "No need to pass options which is never used"
rafaelfranca authored
163 drop_table(table_name, options)
0639e1c @dhh Added :force option to create_table that'll try to drop the table if it ...
dhh authored
164 end
165
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
166 create_sql = "CREATE#{' TEMPORARY' if options[:temporary]} TABLE "
9b6207c @jeremy Quote table names. Defaults to column quoting. Closes #4593.
jeremy authored
167 create_sql << "#{quote_table_name(table_name)} ("
b297911 @tenderlove use inheritence to deal with custom methods
tenderlove authored
168 create_sql << td.to_sql
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
169 create_sql << ") #{options[:options]}"
170 execute create_sql
171 end
9b6207c @jeremy Quote table names. Defaults to column quoting. Closes #4593.
jeremy authored
172
96980bd @dhh Added change_table for migrations (Jeff Dean) [#71 state:resolved]
dhh authored
173 # A block for changing columns in +table+.
174 #
175 # === Example
176 # # change_table() yields a Table instance
177 # change_table(:suppliers) do |t|
178 # t.column :name, :string, :limit => 60
179 # # Other column alterations here
180 # end
181 #
30176f2 @lifo Add :bulk => true option to change_table
lifo authored
182 # The +options+ hash can include the following keys:
183 # [<tt>:bulk</tt>]
184 # Set this to true to make this a bulk alter query, such as
185 # ALTER TABLE `users` ADD COLUMN age INT(11), ADD COLUMN birthdate DATETIME ...
186 #
187 # Defaults to false.
188 #
96980bd @dhh Added change_table for migrations (Jeff Dean) [#71 state:resolved]
dhh authored
189 # ===== Examples
190 # ====== Add a column
191 # change_table(:suppliers) do |t|
192 # t.column :name, :string, :limit => 60
193 # end
194 #
195 # ====== Add 2 integer columns
196 # change_table(:suppliers) do |t|
197 # t.integer :width, :height, :null => false, :default => 0
198 # end
199 #
200 # ====== Add created_at/updated_at columns
201 # change_table(:suppliers) do |t|
202 # t.timestamps
203 # end
204 #
205 # ====== Add a foreign key column
206 # change_table(:suppliers) do |t|
207 # t.references :company
208 # end
209 #
210 # Creates a <tt>company_id(integer)</tt> column
211 #
212 # ====== Add a polymorphic foreign key column
213 # change_table(:suppliers) do |t|
214 # t.belongs_to :company, :polymorphic => true
215 # end
216 #
217 # Creates <tt>company_type(varchar)</tt> and <tt>company_id(integer)</tt> columns
218 #
219 # ====== Remove a column
220 # change_table(:suppliers) do |t|
221 # t.remove :company
222 # end
223 #
46f30f9 @lifo Merge documentation changes from docrails.
lifo authored
224 # ====== Remove several columns
96980bd @dhh Added change_table for migrations (Jeff Dean) [#71 state:resolved]
dhh authored
225 # change_table(:suppliers) do |t|
226 # t.remove :company_id
227 # t.remove :width, :height
228 # end
229 #
230 # ====== Remove an index
231 # change_table(:suppliers) do |t|
232 # t.remove_index :company_id
233 # end
234 #
235 # See also Table for details on
236 # all of the various column transformation
649f251 @tenderlove Revert "Merge pull request #3603 from vijaydev/change_table_without_bloc...
tenderlove authored
237 def change_table(table_name, options = {})
238 if supports_bulk_alter? && options[:bulk]
239 recorder = ActiveRecord::Migration::CommandRecorder.new(self)
240 yield Table.new(table_name, recorder)
241 bulk_change_table(table_name, recorder.commands)
242 else
243 yield Table.new(table_name, self)
30176f2 @lifo Add :bulk => true option to change_table
lifo authored
244 end
96980bd @dhh Added change_table for migrations (Jeff Dean) [#71 state:resolved]
dhh authored
245 end
46f30f9 @lifo Merge documentation changes from docrails.
lifo authored
246
ebfddf3 Add rename_table to mysql, sqlite and postgres adapters for use in migra...
Tobias Lütke authored
247 # Renames a table.
248 # ===== Example
249 # rename_table('octopuses', 'octopi')
9b6207c @jeremy Quote table names. Defaults to column quoting. Closes #4593.
jeremy authored
250 def rename_table(table_name, new_name)
ebfddf3 Add rename_table to mysql, sqlite and postgres adapters for use in migra...
Tobias Lütke authored
251 raise NotImplementedError, "rename_table is not implemented"
252 end
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
253
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
254 # Drops a table from the database.
663904f @rafaelfranca Revert "No need to pass options which is never used"
rafaelfranca authored
255 def drop_table(table_name, options = {})
9b6207c @jeremy Quote table names. Defaults to column quoting. Closes #4593.
jeremy authored
256 execute "DROP TABLE #{quote_table_name(table_name)}"
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
257 end
258
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
259 # Adds a new column to the named table.
260 # See TableDefinition#column for details of the options you can use.
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
261 def add_column(table_name, column_name, type, options = {})
9b6207c @jeremy Quote table names. Defaults to column quoting. Closes #4593.
jeremy authored
262 add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
263 add_column_options!(add_column_sql, options)
264 execute(add_column_sql)
265 end
266
96980bd @dhh Added change_table for migrations (Jeff Dean) [#71 state:resolved]
dhh authored
267 # Removes the column(s) from the table definition.
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
268 # ===== Examples
269 # remove_column(:suppliers, :qualification)
96980bd @dhh Added change_table for migrations (Jeff Dean) [#71 state:resolved]
dhh authored
270 # remove_columns(:suppliers, :qualification, :experience)
271 def remove_column(table_name, *column_names)
30176f2 @lifo Add :bulk => true option to change_table
lifo authored
272 columns_for_remove(table_name, *column_names).each {|column_name| execute "ALTER TABLE #{quote_table_name(table_name)} DROP #{column_name}" }
ebfddf3 Add rename_table to mysql, sqlite and postgres adapters for use in migra...
Tobias Lütke authored
273 end
96980bd @dhh Added change_table for migrations (Jeff Dean) [#71 state:resolved]
dhh authored
274 alias :remove_columns :remove_column
46f30f9 @lifo Merge documentation changes from docrails.
lifo authored
275
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
276 # Changes the column's definition according to the new options.
277 # See TableDefinition#column for details of the options you can use.
278 # ===== Examples
279 # change_column(:suppliers, :name, :string, :limit => 80)
280 # change_column(:accounts, :description, :text)
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
281 def change_column(table_name, column_name, type, options = {})
282 raise NotImplementedError, "change_column is not implemented"
283 end
284
64fe0d4 @manuelmeurer Remove incorrect comment that a default value of NULL cannot be set with...
manuelmeurer authored
285 # Sets a new default value for a column.
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
286 # ===== Examples
287 # change_column_default(:suppliers, :qualification, 'new')
288 # change_column_default(:accounts, :authorized, 1)
64fe0d4 @manuelmeurer Remove incorrect comment that a default value of NULL cannot be set with...
manuelmeurer authored
289 # change_column_default(:users, :email, nil)
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
290 def change_column_default(table_name, column_name, default)
291 raise NotImplementedError, "change_column_default is not implemented"
292 end
293
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
294 # Renames a column.
295 # ===== Example
296 # rename_column(:suppliers, :description, :name)
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
297 def rename_column(table_name, column_name, new_column_name)
298 raise NotImplementedError, "rename_column is not implemented"
299 end
300
0034b78 @smartinez87 Remove extra white spaces on ActiveRecord docs.
smartinez87 authored
301 # Adds a new index to the table. +column_name+ can be a single Symbol, or
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
302 # an Array of Symbols.
303 #
d8a43e2 @joliss Document that index names are made up of all columns, not just the first...
joliss authored
304 # The index will be named after the table and the column name(s), unless
305 # you pass <tt>:name</tt> as an option.
9404654 Add documentation for add_index and remove_index. Closes #3600.
Marcel Molina authored
306 #
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
307 # ===== Examples
8d2f6c1 @lifo Revert "Revert "Add index length support for MySQL [#1852 state:open]""
lifo authored
308 #
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
309 # ====== Creating a simple index
310 # add_index(:suppliers, :name)
311 # generates
312 # CREATE INDEX suppliers_name_index ON suppliers(name)
8d2f6c1 @lifo Revert "Revert "Add index length support for MySQL [#1852 state:open]""
lifo authored
313 #
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
314 # ====== Creating a unique index
315 # add_index(:accounts, [:branch_id, :party_id], :unique => true)
316 # generates
79542f8 @jeremy Migrations: uniquely name multicolumn indexes so you don't have to.
jeremy authored
317 # CREATE UNIQUE INDEX accounts_branch_id_party_id_index ON accounts(branch_id, party_id)
8d2f6c1 @lifo Revert "Revert "Add index length support for MySQL [#1852 state:open]""
lifo authored
318 #
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
319 # ====== Creating a named index
320 # add_index(:accounts, [:branch_id, :party_id], :unique => true, :name => 'by_branch_party')
321 # generates
322 # CREATE UNIQUE INDEX by_branch_party ON accounts(branch_id, party_id)
8d2f6c1 @lifo Revert "Revert "Add index length support for MySQL [#1852 state:open]""
lifo authored
323 #
324 # ====== Creating an index with specific key length
325 # add_index(:accounts, :name, :name => 'by_name', :length => 10)
326 # generates
327 # CREATE INDEX by_name ON accounts(name(10))
328 #
329 # add_index(:accounts, [:name, :surname], :name => 'by_name_surname', :length => {:name => 10, :surname => 15})
330 # generates
331 # CREATE INDEX by_name_surname ON accounts(name(10), surname(15))
332 #
333 # Note: SQLite doesn't support index length
69dcd45 @vjebelev AR changes to support creating ordered (asc, desc) indexes
vjebelev authored
334 #
335 # ====== Creating an index with a sort order (desc or asc, asc is the default)
336 # add_index(:accounts, [:branch_id, :party_id, :surname], :order => {:branch_id => :desc, :part_id => :asc})
337 # generates
338 # CREATE INDEX by_branch_desc_party ON accounts(branch_id DESC, party_id ASC, surname)
339 #
340 # Note: mysql doesn't yet support index order (it accepts the syntax but ignores it)
341 #
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
342 def add_index(table_name, column_name, options = {})
30176f2 @lifo Add :bulk => true option to change_table
lifo authored
343 index_name, index_type, index_columns = add_index_options(table_name, column_name, options)
344 execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{index_columns})"
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
345 end
346
347 # Remove the given index from the table.
348 #
144a388 @raviolicode Update remove_index documentation
raviolicode authored
349 # Remove the index_accounts_on_column in the accounts table.
350 # remove_index :accounts, :column
351 # Remove the index named index_accounts_on_branch_id in the accounts table.
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
352 # remove_index :accounts, :column => :branch_id
144a388 @raviolicode Update remove_index documentation
raviolicode authored
353 # Remove the index named index_accounts_on_branch_id_and_party_id in the accounts table.
79542f8 @jeremy Migrations: uniquely name multicolumn indexes so you don't have to.
jeremy authored
354 # remove_index :accounts, :column => [:branch_id, :party_id]
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
355 # Remove the index named by_branch_party in the accounts table.
356 # remove_index :accounts, :name => :by_branch_party
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
357 def remove_index(table_name, options = {})
30176f2 @lifo Add :bulk => true option to change_table
lifo authored
358 remove_index!(table_name, index_name_for_remove(table_name, options))
3809c80 @etiennebarrie make add_index and remove_index more resilient; new rename_index method;...
etiennebarrie authored
359 end
360
361 def remove_index!(table_name, index_name) #:nodoc:
ff22b9d @pupeno Fixed error when removing an index from a table name values, which is a ...
pupeno authored
362 execute "DROP INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)}"
3809c80 @etiennebarrie make add_index and remove_index more resilient; new rename_index method;...
etiennebarrie authored
363 end
364
365 # Rename an index.
366 #
367 # Rename the index_people_on_last_name index to index_users_on_last_name
368 # rename_index :people, 'index_people_on_last_name', 'index_users_on_last_name'
369 def rename_index(table_name, old_name, new_name)
370 # this is a naive implementation; some DBs may support this more efficiently (Postgres, for instance)
371 old_index_def = indexes(table_name).detect { |i| i.name == old_name }
372 return unless old_index_def
373 remove_index(table_name, :name => old_name)
374 add_index(table_name, old_index_def.columns, :name => new_name, :unique => old_index_def.unique)
816f37a @dhh Added migration support to SQL Server adapter (please someone do the sam...
dhh authored
375 end
376
377 def index_name(table_name, options) #:nodoc:
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
378 if Hash === options # legacy support
379 if options[:column]
86dda36 @jeremy Avoid deprecated String#to_a by using Array.wrap(...) instead of Array(....
jeremy authored
380 "index_#{table_name}_on_#{Array.wrap(options[:column]) * '_and_'}"
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
381 elsif options[:name]
816f37a @dhh Added migration support to SQL Server adapter (please someone do the sam...
dhh authored
382 options[:name]
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
383 else
384 raise ArgumentError, "You must specify the index name"
385 end
386 else
79542f8 @jeremy Migrations: uniquely name multicolumn indexes so you don't have to.
jeremy authored
387 index_name(table_name, :column => options)
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
388 end
389 end
390
11ff3da @pixeltrix Add column and index query methods to ActiveRecord::Schema
pixeltrix authored
391 # Verify the existence of an index with a given name.
3809c80 @etiennebarrie make add_index and remove_index more resilient; new rename_index method;...
etiennebarrie authored
392 #
393 # The default argument is returned if the underlying implementation does not define the indexes method,
394 # as there's no way to determine the correct answer in that case.
11ff3da @pixeltrix Add column and index query methods to ActiveRecord::Schema
pixeltrix authored
395 def index_name_exists?(table_name, index_name, default)
3809c80 @etiennebarrie make add_index and remove_index more resilient; new rename_index method;...
etiennebarrie authored
396 return default unless respond_to?(:indexes)
8b8730e @etiennebarrie Test add_index and remove_index with a symbol name #4891
etiennebarrie authored
397 index_name = index_name.to_s
398 indexes(table_name).detect { |i| i.name == index_name }
3809c80 @etiennebarrie make add_index and remove_index more resilient; new rename_index method;...
etiennebarrie authored
399 end
400
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
401 # Returns a string of <tt>CREATE TABLE</tt> SQL statement(s) for recreating the
402 # entire structure of the database.
403 def structure_dump
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
404 end
405
04d8554 @pd Restore dump_schema_information connection adapter method
pd authored
406 def dump_schema_information #:nodoc:
407 sm_table = ActiveRecord::Migrator.schema_migrations_table_name
ff9c279 @rud dump_schema_information: explicitly order inserts into schema_migrations...
rud authored
408 migrated = select_values("SELECT version FROM #{sm_table} ORDER BY version")
2183c22 @ssoroka Make sure clone_structure can load the results of dump_schema_informatio...
ssoroka authored
409 migrated.map { |v| "INSERT INTO #{sm_table} (version) VALUES ('#{v}');" }.join("\n\n")
04d8554 @pd Restore dump_schema_information connection adapter method
pd authored
410 end
411
b9fa354 Add extensive documentation to the ActiveRecord::AbstractAdapter. #2250
Marcel Molina authored
412 # Should not be called normally, but this operation is non-destructive.
413 # The migrations module handles this automatically.
8a5a9dc @technoweenie Add support for interleaving migrations by storing which migrations have...
technoweenie authored
414 def initialize_schema_migrations_table
415 sm_table = ActiveRecord::Migrator.schema_migrations_table_name
416
3ec212e @tenderlove rolling out migrated_at until I can fix the build
tenderlove authored
417 unless table_exists?(sm_table)
8a5a9dc @technoweenie Add support for interleaving migrations by storing which migrations have...
technoweenie authored
418 create_table(sm_table, :id => false) do |schema_migrations_table|
419 schema_migrations_table.column :version, :string, :null => false
c00de99 @dhh Switched to UTC-timebased version numbers for migrations and the schema....
dhh authored
420 end
8a5a9dc @technoweenie Add support for interleaving migrations by storing which migrations have...
technoweenie authored
421 add_index sm_table, :version, :unique => true,
7eaed4f Use table prefix and suffix for schema_migrations index.
Tim Peters authored
422 :name => "#{Base.table_name_prefix}unique_schema_migrations#{Base.table_name_suffix}"
8a5a9dc @technoweenie Add support for interleaving migrations by storing which migrations have...
technoweenie authored
423
424 # Backwards-compatibility: if we find schema_info, assume we've
425 # migrated up to that point:
426 si_table = Base.table_name_prefix + 'schema_info' + Base.table_name_suffix
427
b193f23 @metaskills Use table_exists? in #initialize_schema_migrations_table [#1923 state:re...
metaskills authored
428 if table_exists?(si_table)
daa2665 @skult Fix Issue #4819
skult authored
429 ActiveSupport::Deprecation.warn "Usage of the schema table `#{si_table}` is deprecated. Please switch to using `schema_migrations` table"
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
430
8a5a9dc @technoweenie Add support for interleaving migrations by storing which migrations have...
technoweenie authored
431 old_version = select_value("SELECT version FROM #{quote_table_name(si_table)}").to_i
432 assume_migrated_upto_version(old_version)
433 drop_table(si_table)
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
434 end
435 end
436 end
437
d0467e0 @drogus Allow to run migrations from more than one directory
drogus authored
438 def assume_migrated_upto_version(version, migrations_paths = ActiveRecord::Migrator.migrations_paths)
e128101 @drogus Use Array.wrap instead of using ternary
drogus authored
439 migrations_paths = Array.wrap(migrations_paths)
e660055 @jeremy Give a nice message if there are duplicate migrations instead of raising...
jeremy authored
440 version = version.to_i
8a5a9dc @technoweenie Add support for interleaving migrations by storing which migrations have...
technoweenie authored
441 sm_table = quote_table_name(ActiveRecord::Migrator.schema_migrations_table_name)
e660055 @jeremy Give a nice message if there are duplicate migrations instead of raising...
jeremy authored
442
a7eb8d9 @sikachu Removing most of the symbol to proc usage in Active Record
sikachu authored
443 migrated = select_values("SELECT version FROM #{sm_table}").map { |v| v.to_i }
d0467e0 @drogus Allow to run migrations from more than one directory
drogus authored
444 paths = migrations_paths.map {|p| "#{p}/[0-9]*_*.rb" }
445 versions = Dir[*paths].map do |filename|
8a5a9dc @technoweenie Add support for interleaving migrations by storing which migrations have...
technoweenie authored
446 filename.split('/').last.split('_').first.to_i
447 end
448
e660055 @jeremy Give a nice message if there are duplicate migrations instead of raising...
jeremy authored
449 unless migrated.include?(version)
3ec212e @tenderlove rolling out migrated_at until I can fix the build
tenderlove authored
450 execute "INSERT INTO #{sm_table} (version) VALUES ('#{version}')"
e660055 @jeremy Give a nice message if there are duplicate migrations instead of raising...
jeremy authored
451 end
452
453 inserted = Set.new
454 (versions - migrated).each do |v|
455 if inserted.include?(v)
456 raise "Duplicate migration #{v}. Please renumber your migrations to resolve the conflict."
457 elsif v < version
3ec212e @tenderlove rolling out migrated_at until I can fix the build
tenderlove authored
458 execute "INSERT INTO #{sm_table} (version) VALUES ('#{v}')"
e660055 @jeremy Give a nice message if there are duplicate migrations instead of raising...
jeremy authored
459 inserted << v
460 end
8a5a9dc @technoweenie Add support for interleaving migrations by storing which migrations have...
technoweenie authored
461 end
462 end
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
463
2a12b56 @jeremy r4704@asus: jeremy | 2006-06-27 12:00:19 -0700
jeremy authored
464 def type_to_sql(type, limit = nil, precision = nil, scale = nil) #:nodoc:
30176f2 @lifo Add :bulk => true option to change_table
lifo authored
465 if native = native_database_types[type.to_sym]
def594b @jeremy Don't append limit to primary key column definition. Freeze some constan...
jeremy authored
466 column_type_sql = (native.is_a?(Hash) ? native[:name] : native).dup
b4e3b5d @jeremy Ruby 1.9 compat: check column type more carefully
jeremy authored
467
e3b49c0 @dhh Fixed spelling errors (closes #9706) [tarmo/rmm5t]
dhh authored
468 if type == :decimal # ignore limit, use precision and scale
38deb0e @jeremy Migrations: add_column supports custom column types. Closes #7742. First...
jeremy authored
469 scale ||= native[:scale]
b4e3b5d @jeremy Ruby 1.9 compat: check column type more carefully
jeremy authored
470
471 if precision ||= native[:precision]
38deb0e @jeremy Migrations: add_column supports custom column types. Closes #7742. First...
jeremy authored
472 if scale
473 column_type_sql << "(#{precision},#{scale})"
474 else
475 column_type_sql << "(#{precision})"
476 end
b4e3b5d @jeremy Ruby 1.9 compat: check column type more carefully
jeremy authored
477 elsif scale
478 raise ArgumentError, "Error adding decimal column: precision cannot be empty if scale if specified"
2a12b56 @jeremy r4704@asus: jeremy | 2006-06-27 12:00:19 -0700
jeremy authored
479 end
b4e3b5d @jeremy Ruby 1.9 compat: check column type more carefully
jeremy authored
480
def594b @jeremy Don't append limit to primary key column definition. Freeze some constan...
jeremy authored
481 elsif (type != :primary_key) && (limit ||= native.is_a?(Hash) && native[:limit])
b4e3b5d @jeremy Ruby 1.9 compat: check column type more carefully
jeremy authored
482 column_type_sql << "(#{limit})"
2a12b56 @jeremy r4704@asus: jeremy | 2006-06-27 12:00:19 -0700
jeremy authored
483 end
b4e3b5d @jeremy Ruby 1.9 compat: check column type more carefully
jeremy authored
484
485 column_type_sql
2a12b56 @jeremy r4704@asus: jeremy | 2006-06-27 12:00:19 -0700
jeremy authored
486 else
b4e3b5d @jeremy Ruby 1.9 compat: check column type more carefully
jeremy authored
487 type
2a12b56 @jeremy r4704@asus: jeremy | 2006-06-27 12:00:19 -0700
jeremy authored
488 end
6019c26 @jeremy change_column accepts :default => nil. Closes #6956.
jeremy authored
489 end
490
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
491 def add_column_options!(sql, options) #:nodoc:
6019c26 @jeremy change_column accepts :default => nil. Closes #6956.
jeremy authored
492 sql << " DEFAULT #{quote(options[:default], options[:column])}" if options_include_default?(options)
0432d15 @lifo Merge with docrails.
lifo authored
493 # must explicitly check for :null to allow change_column to work on migrations
74c3c70 @tarmo Don't set "NULL" as a constraint on nullable columns [#398 state:resolve...
tarmo authored
494 if options[:null] == false
495 sql << " NOT NULL"
10ef65a Fixed that change_column should be able to use :null => true on a field ...
David Heinemeier Hansson authored
496 end
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
497 end
e789b26 @technoweenie fix select_limited_ids_list issues in postgresql, retain current behavio...
technoweenie authored
498
c0bce43 @jeremy Oracle: fix limited id selection for eager loading. Closes #6515.
jeremy authored
499 # SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause.
500 # Both PostgreSQL and Oracle overrides this for custom DISTINCT syntax.
501 #
502 # distinct("posts.id", "posts.created_at desc")
503 def distinct(columns, order_by)
e789b26 @technoweenie fix select_limited_ids_list issues in postgresql, retain current behavio...
technoweenie authored
504 "DISTINCT #{columns}"
505 end
46f30f9 @lifo Merge documentation changes from docrails.
lifo authored
506
bcb47a8 @dhh Added add/remove_timestamps to the schema statements for adding the crea...
dhh authored
507 # Adds timestamps (created_at and updated_at) columns to the named table.
508 # ===== Examples
509 # add_timestamps(:suppliers)
510 def add_timestamps(table_name)
bbe7dac @fxn revert setting NOT NULL constraints in add_timestamps
fxn authored
511 add_column table_name, :created_at, :datetime
512 add_column table_name, :updated_at, :datetime
bcb47a8 @dhh Added add/remove_timestamps to the schema statements for adding the crea...
dhh authored
513 end
46f30f9 @lifo Merge documentation changes from docrails.
lifo authored
514
bcb47a8 @dhh Added add/remove_timestamps to the schema statements for adding the crea...
dhh authored
515 # Removes the timestamp columns (created_at and updated_at) from the table definition.
516 # ===== Examples
517 # remove_timestamps(:suppliers)
518 def remove_timestamps(table_name)
46f30f9 @lifo Merge documentation changes from docrails.
lifo authored
519 remove_column table_name, :updated_at
520 remove_column table_name, :created_at
bcb47a8 @dhh Added add/remove_timestamps to the schema statements for adding the crea...
dhh authored
521 end
46f30f9 @lifo Merge documentation changes from docrails.
lifo authored
522
6019c26 @jeremy change_column accepts :default => nil. Closes #6956.
jeremy authored
523 protected
69dcd45 @vjebelev AR changes to support creating ordered (asc, desc) indexes
vjebelev authored
524 def add_index_sort_order(option_strings, column_names, options = {})
525 if options.is_a?(Hash) && order = options[:order]
526 case order
527 when Hash
528 column_names.each {|name| option_strings[name] += " #{order[name].to_s.upcase}" if order.has_key?(name)}
529 when String
530 column_names.each {|name| option_strings[name] += " #{order.upcase}"}
531 end
532 end
533
534 return option_strings
535 end
536
8d2f6c1 @lifo Revert "Revert "Add index length support for MySQL [#1852 state:open]""
lifo authored
537 # Overridden by the mysql adapter for supporting index lengths
538 def quoted_columns_for_index(column_names, options = {})
69dcd45 @vjebelev AR changes to support creating ordered (asc, desc) indexes
vjebelev authored
539 option_strings = Hash[column_names.map {|name| [name, '']}]
540
541 # add index sort order if supported
542 if supports_index_sort_order?
543 option_strings = add_index_sort_order(option_strings, column_names, options)
544 end
545
546 column_names.map {|name| quote_column_name(name) + option_strings[name]}
8d2f6c1 @lifo Revert "Revert "Add index length support for MySQL [#1852 state:open]""
lifo authored
547 end
548
6019c26 @jeremy change_column accepts :default => nil. Closes #6956.
jeremy authored
549 def options_include_default?(options)
550 options.include?(:default) && !(options[:null] == false && options[:default].nil?)
551 end
b297911 @tenderlove use inheritence to deal with custom methods
tenderlove authored
552
30176f2 @lifo Add :bulk => true option to change_table
lifo authored
553 def add_index_options(table_name, column_name, options = {})
554 column_names = Array.wrap(column_name)
555 index_name = index_name(table_name, :column => column_names)
556
557 if Hash === options # legacy support, since this param was a string
558 index_type = options[:unique] ? "UNIQUE" : ""
559 index_name = options[:name].to_s if options.key?(:name)
560 else
561 index_type = options
562 end
563
564 if index_name.length > index_name_length
565 raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' is too long; the limit is #{index_name_length} characters"
566 end
567 if index_name_exists?(table_name, index_name, false)
568 raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists"
569 end
570 index_columns = quoted_columns_for_index(column_names, options).join(", ")
571
572 [index_name, index_type, index_columns]
573 end
574
575 def index_name_for_remove(table_name, options = {})
576 index_name = index_name(table_name, options)
577
578 unless index_name_exists?(table_name, index_name, true)
579 raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' does not exist"
580 end
581
582 index_name
583 end
584
585 def columns_for_remove(table_name, *column_names)
586 column_names = column_names.flatten
587
05f29ca @smartinez87 Remove extra white-space on some exception messages.
smartinez87 authored
588 raise ArgumentError.new("You must specify at least one column name. Example: remove_column(:people, :first_name)") if column_names.blank?
30176f2 @lifo Add :bulk => true option to change_table
lifo authored
589 column_names.map {|column_name| quote_column_name(column_name) }
590 end
591
b297911 @tenderlove use inheritence to deal with custom methods
tenderlove authored
592 private
593 def table_definition
594 TableDefinition.new(self)
595 end
b3df959 @dhh Refactored the AbstractAdapter to be a lot less scary. Cleaned up the do...
dhh authored
596 end
597 end
b25933f Get rid of warnings generated by calling obsolete .to_a method on a Symb...
Marcel Molina authored
598 end
Something went wrong with that request. Please try again.