Module: ActiveRecord::ConnectionAdapters::SchemaStatements
- Included in:
- AbstractAdapter
- Defined in:
- lib/active_record/connection_adapters/abstract/schema_statements.rb
Instance Method Summary collapse
-
#add_column(table_name, column_name, type, options = {}) ⇒ Object
Adds a new column to the named table.
-
#add_column_options!(sql, options) ⇒ Object
:nodoc:.
-
#add_index(table_name, column_name, options = {}) ⇒ Object
Adds a new index to the table.
-
#add_order_by_for_association_limiting!(sql, options) ⇒ Object
ORDER BY clause for the passed order option.
-
#add_timestamps(table_name) ⇒ Object
Adds timestamps (created_at and updated_at) columns to the named table.
- #assume_migrated_upto_version(version) ⇒ Object
-
#change_column(table_name, column_name, type, options = {}) ⇒ Object
Changes the column’s definition according to the new options.
-
#change_column_default(table_name, column_name, default) ⇒ Object
Sets a new default value for a column.
-
#change_table(table_name) {|Table.new(table_name, self)| ... } ⇒ Object
A block for changing columns in
table
. -
#columns(table_name, name = nil) ⇒ Object
Returns an array of Column objects for the table specified by
table_name
. -
#create_table(table_name, options = {}) {|table_definition| ... } ⇒ Object
Creates a new table with the name
table_name
. -
#distinct(columns, order_by) ⇒ Object
SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause.
-
#drop_table(table_name, options = {}) ⇒ Object
Drops a table from the database.
-
#dump_schema_information ⇒ Object
:nodoc:.
-
#index_name(table_name, options) ⇒ Object
:nodoc:.
-
#initialize_schema_migrations_table ⇒ Object
Should not be called normally, but this operation is non-destructive.
-
#native_database_types ⇒ Object
Returns a Hash of mappings from the abstract data types to the native database types.
-
#remove_column(table_name, *column_names) ⇒ Object
(also: #remove_columns)
Removes the column(s) from the table definition.
-
#remove_index(table_name, options = {}) ⇒ Object
Remove the given index from the table.
-
#remove_timestamps(table_name) ⇒ Object
Removes the timestamp columns (created_at and updated_at) from the table definition.
-
#rename_column(table_name, column_name, new_column_name) ⇒ Object
Renames a column.
-
#rename_table(table_name, new_name) ⇒ Object
Renames a table.
-
#structure_dump ⇒ Object
Returns a string of
CREATE TABLE
SQL statement(s) for recreating the entire structure of the database. -
#table_alias_for(table_name) ⇒ Object
Truncates a table alias according to the limits of the current adapter.
-
#table_alias_length ⇒ Object
This is the maximum length a table alias can be.
-
#table_exists?(table_name) ⇒ Boolean
def tables(name = nil) end.
-
#type_to_sql(type, limit = nil, precision = nil, scale = nil) ⇒ Object
:nodoc:.
Instance Method Details
#add_column(table_name, column_name, type, options = {}) ⇒ Object
Adds a new column to the named table. See TableDefinition#column for details of the options you can use.
192 193 194 195 196 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 192 def add_column(table_name, column_name, type, = {}) add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD #{quote_column_name(column_name)} #{type_to_sql(type, [:limit], [:precision], [:scale])}" (add_column_sql, ) execute(add_column_sql) end |
#add_column_options!(sql, options) ⇒ Object
:nodoc:
390 391 392 393 394 395 396 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 390 def (sql, ) #:nodoc: sql << " DEFAULT #{quote([:default], [:column])}" if () # must explicitly check for :null to allow change_column to work on migrations if [:null] == false sql << " NOT NULL" end end |
#add_index(table_name, column_name, options = {}) ⇒ Object
Adds a new index to the table. column_name
can be a single Symbol, or an Array of Symbols.
The index will be named after the table and the first column name, unless you pass :name
as an option.
When creating an index on multiple columns, the first column is used as a name for the index. For example, when you specify an index on two columns [:first
, :last
], the DBMS creates an index for both columns as well as an index for the first column :first
. Using just the first name for this index makes sense, because you will never have to create a singular index with this name.
Examples
Creating a simple index
add_index(:suppliers, :name)
generates
CREATE INDEX suppliers_name_index ON suppliers(name)
Creating a unique index
add_index(:accounts, [:branch_id, :party_id], :unique => true)
generates
CREATE UNIQUE INDEX accounts_branch_id_party_id_index ON accounts(branch_id, party_id)
Creating a named index
add_index(:accounts, [:branch_id, :party_id], :unique => true, :name => 'by_branch_party')
generates
CREATE UNIQUE INDEX by_branch_party ON accounts(branch_id, party_id)
261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 261 def add_index(table_name, column_name, = {}) column_names = Array(column_name) index_name = index_name(table_name, :column => column_names) if Hash === # legacy support, since this param was a string index_type = [:unique] ? "UNIQUE" : "" index_name = [:name] || index_name else index_type = end quoted_column_names = column_names.map { |e| quote_column_name(e) }.join(", ") execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names})" end |
#add_order_by_for_association_limiting!(sql, options) ⇒ Object
ORDER BY clause for the passed order option. PostgreSQL overrides this due to its stricter standards compliance.
408 409 410 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 408 def add_order_by_for_association_limiting!(sql, ) sql << " ORDER BY #{[:order]}" end |
#add_timestamps(table_name) ⇒ Object
Adds timestamps (created_at and updated_at) columns to the named table.
Examples
(:suppliers)
415 416 417 418 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 415 def (table_name) add_column table_name, :created_at, :datetime add_column table_name, :updated_at, :datetime end |
#assume_migrated_upto_version(version) ⇒ Object
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 339 def assume_migrated_upto_version(version) version = version.to_i sm_table = quote_table_name(ActiveRecord::Migrator.schema_migrations_table_name) migrated = select_values("SELECT version FROM #{sm_table}").map(&:to_i) versions = Dir['db/migrate/[0-9]*_*.rb'].map do |filename| filename.split('/').last.split('_').first.to_i end unless migrated.include?(version) execute "INSERT INTO #{sm_table} (version) VALUES ('#{version}')" end inserted = Set.new (versions - migrated).each do |v| if inserted.include?(v) raise "Duplicate migration #{v}. Please renumber your migrations to resolve the conflict." elsif v < version execute "INSERT INTO #{sm_table} (version) VALUES ('#{v}')" inserted << v end end end |
#change_column(table_name, column_name, type, options = {}) ⇒ Object
Changes the column’s definition according to the new options. See TableDefinition#column for details of the options you can use.
Examples
change_column(:suppliers, :name, :string, :limit => 80)
change_column(:accounts, :description, :text)
214 215 216 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 214 def change_column(table_name, column_name, type, = {}) raise NotImplementedError, "change_column is not implemented" end |
#change_column_default(table_name, column_name, default) ⇒ Object
Sets a new default value for a column. If you want to set the default value to NULL
, you are out of luck. You need to DatabaseStatements#execute the appropriate SQL statement yourself.
Examples
change_column_default(:suppliers, :qualification, 'new')
change_column_default(:accounts, :authorized, 1)
224 225 226 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 224 def change_column_default(table_name, column_name, default) raise NotImplementedError, "change_column_default is not implemented" end |
#change_table(table_name) {|Table.new(table_name, self)| ... } ⇒ Object
A block for changing columns in table
.
Example
# change_table() yields a Table instance
change_table(:suppliers) do |t|
t.column :name, :string, :limit => 60
# Other column alterations here
end
Examples
Add a column
change_table(:suppliers) do |t|
t.column :name, :string, :limit => 60
end
Add 2 integer columns
change_table(:suppliers) do |t|
t.integer :width, :height, :null => false, :default => 0
end
Add created_at/updated_at columns
change_table(:suppliers) do |t|
t.
end
Add a foreign key column
change_table(:suppliers) do |t|
t.references :company
end
Creates a company_id(integer)
column
Add a polymorphic foreign key column
change_table(:suppliers) do |t|
t.belongs_to :company, :polymorphic => true
end
Creates company_type(varchar)
and company_id(integer)
columns
Remove a column
change_table(:suppliers) do |t|
t.remove :company
end
Remove several columns
change_table(:suppliers) do |t|
t.remove :company_id
t.remove :width, :height
end
Remove an index
change_table(:suppliers) do |t|
t.remove_index :company_id
end
See also Table for details on all of the various column transformation
174 175 176 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 174 def change_table(table_name) yield Table.new(table_name, self) end |
#columns(table_name, name = nil) ⇒ Object
Returns an array of Column objects for the table specified by table_name
. See the concrete implementation for details on the expected parameter values.
32 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 32 def columns(table_name, name = nil) end |
#create_table(table_name, options = {}) {|table_definition| ... } ⇒ Object
Creates a new table with the name table_name
. table_name
may either be a String or a Symbol.
There are two ways to work with create_table
. You can use the block form or the regular form, like this:
Block form
# create_table() passes a TableDefinition object to the block.
# This form will not only create the table, but also columns for the
# table.
create_table(:suppliers) do |t|
t.column :name, :string, :limit => 60
# Other fields here
end
Regular form
# Creates a table called 'suppliers' with no columns.
create_table(:suppliers)
# Add a column to 'suppliers'.
add_column(:suppliers, :name, :string, {:limit => 60})
The options
hash can include the following keys:
:id
-
Whether to automatically add a primary key column. Defaults to true. Join tables for
has_and_belongs_to_many
should set:id => false
. :primary_key
-
The name of the primary key, if one is to be added automatically. Defaults to
id
. :options
-
Any extra options you want appended to the table definition.
:temporary
-
Make a temporary table.
:force
-
Set to true to drop the table before creating it. Defaults to false.
Examples
Add a backend specific option to the generated SQL (MySQL)
create_table(:suppliers, :options => 'ENGINE=InnoDB DEFAULT CHARSET=utf8')
generates:
CREATE TABLE suppliers (
id int(11) DEFAULT NULL auto_increment PRIMARY KEY
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Rename the primary key column
create_table(:objects, :primary_key => 'guid') do |t|
t.column :name, :string, :limit => 80
end
generates:
CREATE TABLE objects (
guid int(11) DEFAULT NULL auto_increment PRIMARY KEY,
name varchar(80)
)
Do not add a primary key column
create_table(:categories_suppliers, :id => false) do |t|
t.column :category_id, :integer
t.column :supplier_id, :integer
end
generates:
CREATE TABLE categories_suppliers (
category_id int,
supplier_id int
)
See also TableDefinition#column for details on how to create columns.
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 100 def create_table(table_name, = {}) table_definition = TableDefinition.new(self) table_definition.primary_key([:primary_key] || Base.get_primary_key(table_name)) unless [:id] == false yield table_definition if [:force] && table_exists?(table_name) drop_table(table_name, ) end create_sql = "CREATE#{' TEMPORARY' if [:temporary]} TABLE " create_sql << "#{quote_table_name(table_name)} (" create_sql << table_definition.to_sql create_sql << ") #{[:options]}" execute create_sql end |
#distinct(columns, order_by) ⇒ Object
SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause. Both PostgreSQL and Oracle overrides this for custom DISTINCT syntax.
distinct("posts.id", "posts.created_at desc")
402 403 404 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 402 def distinct(columns, order_by) "DISTINCT #{columns}" end |
#drop_table(table_name, options = {}) ⇒ Object
Drops a table from the database.
186 187 188 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 186 def drop_table(table_name, = {}) execute "DROP TABLE #{quote_table_name(table_name)}" end |
#dump_schema_information ⇒ Object
:nodoc:
308 309 310 311 312 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 308 def dump_schema_information #:nodoc: sm_table = ActiveRecord::Migrator.schema_migrations_table_name migrated = select_values("SELECT version FROM #{sm_table}") migrated.map { |v| "INSERT INTO #{sm_table} (version) VALUES ('#{v}');" }.join("\n\n") end |
#index_name(table_name, options) ⇒ Object
:nodoc:
289 290 291 292 293 294 295 296 297 298 299 300 301 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 289 def index_name(table_name, ) #:nodoc: if Hash === # legacy support if [:column] "index_#{table_name}_on_#{Array([:column]) * '_and_'}" elsif [:name] [:name] else raise ArgumentError, "You must specify the index name" end else index_name(table_name, :column => ) end end |
#initialize_schema_migrations_table ⇒ Object
Should not be called normally, but this operation is non-destructive. The migrations module handles this automatically.
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 316 def initialize_schema_migrations_table sm_table = ActiveRecord::Migrator.schema_migrations_table_name unless tables.detect { |t| t == sm_table } create_table(sm_table, :id => false) do |schema_migrations_table| schema_migrations_table.column :version, :string, :null => false end add_index sm_table, :version, :unique => true, :name => 'unique_schema_migrations' # Backwards-compatibility: if we find schema_info, assume we've # migrated up to that point: si_table = Base.table_name_prefix + 'schema_info' + Base.table_name_suffix if tables.detect { |t| t == si_table } old_version = select_value("SELECT version FROM #{quote_table_name(si_table)}").to_i assume_migrated_upto_version(old_version) drop_table(si_table) end end end |
#native_database_types ⇒ Object
Returns a Hash of mappings from the abstract data types to the native database types. See TableDefinition#column for details on the recognized abstract data types.
7 8 9 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 7 def native_database_types {} end |
#remove_column(table_name, *column_names) ⇒ Object Also known as: remove_columns
Removes the column(s) from the table definition.
Examples
remove_column(:suppliers, :qualification)
remove_columns(:suppliers, :qualification, :experience)
202 203 204 205 206 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 202 def remove_column(table_name, *column_names) column_names.flatten.each do |column_name| execute "ALTER TABLE #{quote_table_name(table_name)} DROP #{quote_column_name(column_name)}" end end |
#remove_index(table_name, options = {}) ⇒ Object
Remove the given index from the table.
Remove the suppliers_name_index in the suppliers table.
remove_index :suppliers, :name
Remove the index named accounts_branch_id_index in the accounts table.
remove_index :accounts, :column => :branch_id
Remove the index named accounts_branch_id_party_id_index in the accounts table.
remove_index :accounts, :column => [:branch_id, :party_id]
Remove the index named by_branch_party in the accounts table.
remove_index :accounts, :name => :by_branch_party
285 286 287 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 285 def remove_index(table_name, = {}) execute "DROP INDEX #{quote_column_name(index_name(table_name, ))} ON #{table_name}" end |
#remove_timestamps(table_name) ⇒ Object
Removes the timestamp columns (created_at and updated_at) from the table definition.
Examples
(:suppliers)
423 424 425 426 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 423 def (table_name) remove_column table_name, :updated_at remove_column table_name, :created_at end |
#rename_column(table_name, column_name, new_column_name) ⇒ Object
Renames a column.
Example
rename_column(:suppliers, :description, :name)
231 232 233 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 231 def rename_column(table_name, column_name, new_column_name) raise NotImplementedError, "rename_column is not implemented" end |
#rename_table(table_name, new_name) ⇒ Object
Renames a table.
Example
rename_table('octopuses', 'octopi')
181 182 183 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 181 def rename_table(table_name, new_name) raise NotImplementedError, "rename_table is not implemented" end |
#structure_dump ⇒ Object
Returns a string of CREATE TABLE
SQL statement(s) for recreating the entire structure of the database.
305 306 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 305 def structure_dump end |
#table_alias_for(table_name) ⇒ Object
Truncates a table alias according to the limits of the current adapter.
17 18 19 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 17 def table_alias_for(table_name) table_name[0..table_alias_length-1].gsub(/\./, '_') end |
#table_alias_length ⇒ Object
This is the maximum length a table alias can be
12 13 14 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 12 def table_alias_length 255 end |
#table_exists?(table_name) ⇒ Boolean
def tables(name = nil) end
23 24 25 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 23 def table_exists?(table_name) tables.include?(table_name.to_s) end |
#type_to_sql(type, limit = nil, precision = nil, scale = nil) ⇒ Object
:nodoc:
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 |
# File 'lib/active_record/connection_adapters/abstract/schema_statements.rb', line 363 def type_to_sql(type, limit = nil, precision = nil, scale = nil) #:nodoc: if native = native_database_types[type] column_type_sql = (native.is_a?(Hash) ? native[:name] : native).dup if type == :decimal # ignore limit, use precision and scale scale ||= native[:scale] if precision ||= native[:precision] if scale column_type_sql << "(#{precision},#{scale})" else column_type_sql << "(#{precision})" end elsif scale raise ArgumentError, "Error adding decimal column: precision cannot be empty if scale if specified" end elsif (type != :primary_key) && (limit ||= native.is_a?(Hash) && native[:limit]) column_type_sql << "(#{limit})" end column_type_sql else type end end |