aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/connection_adapters
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/connection_adapters')
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb3
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb194
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb84
-rwxr-xr-xactiverecord/lib/active_record/connection_adapters/mysql_adapter.rb20
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb8
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb9
6 files changed, 300 insertions, 18 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb
index d950181566..34627dfaf9 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb
@@ -175,7 +175,7 @@ module ActiveRecord
end
# Establishes the connection to the database. Accepts a hash as input where
- # the :adapter key must be specified with the name of a database adapter (in lower-case)
+ # the <tt>:adapter</tt> key must be specified with the name of a database adapter (in lower-case)
# example for regular databases (MySQL, Postgresql, etc):
#
# ActiveRecord::Base.establish_connection(
@@ -194,6 +194,7 @@ module ActiveRecord
# )
#
# Also accepts keys as strings (for parsing from yaml for example):
+ #
# ActiveRecord::Base.establish_connection(
# "adapter" => "sqlite",
# "database" => "path/to/dbfile"
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
index d30f9b4d32..d73ffc3da6 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
@@ -398,8 +398,8 @@ module ActiveRecord
# TableDefinition#timestamps that'll add created_at and updated_at as datetimes.
#
# TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type
- # column if the :polymorphic option is supplied. If :polymorphic is a hash of options, these will be
- # used when creating the _type column. So what can be written like this:
+ # column if the <tt>:polymorphic</tt> option is supplied. If <tt>:polymorphic</tt> is a hash of options, these will be
+ # used when creating the <tt>_type</tt> column. So what can be written like this:
#
# create_table :taggings do |t|
# t.integer :tag_id, :tagger_id, :taggable_id
@@ -469,5 +469,195 @@ module ActiveRecord
@base.native_database_types
end
end
+
+ # Represents a SQL table in an abstract way for updating a table.
+ # Also see TableDefinition and SchemaStatements#create_table
+ #
+ # Available transformations are:
+ #
+ # change_table :table do |t|
+ # t.column
+ # t.index
+ # t.timestamps
+ # t.change
+ # t.change_default
+ # t.rename
+ # t.references
+ # t.belongs_to
+ # t.string
+ # t.text
+ # t.integer
+ # t.float
+ # t.decimal
+ # t.datetime
+ # t.timestamp
+ # t.time
+ # t.date
+ # t.binary
+ # t.boolean
+ # t.remove
+ # t.remove_references
+ # t.remove_belongs_to
+ # t.remove_index
+ # t.remove_timestamps
+ # end
+ #
+ class Table
+ def initialize(table_name, base)
+ @table_name = table_name
+ @base = base
+ end
+
+ # Adds a new column to the named table.
+ # See TableDefinition#column for details of the options you can use.
+ # ===== Examples
+ # ====== Creating a simple columns
+ # t.column(:name, :string)
+ def column(column_name, type, options = {})
+ @base.add_column(@table_name, column_name, type, options)
+ end
+
+ # Adds a new index to the table. +column_name+ can be a single Symbol, or
+ # an Array of Symbols. See SchemaStatements#add_index
+ #
+ # ===== Examples
+ # ====== Creating a simple index
+ # t.index(:name)
+ # ====== Creating a unique index
+ # t.index([:branch_id, :party_id], :unique => true)
+ # ====== Creating a named index
+ # t.index([:branch_id, :party_id], :unique => true, :name => 'by_branch_party')
+ def index(column_name, options = {})
+ @base.add_index(@table_name, column_name, options)
+ end
+
+ # Adds timestamps (created_at and updated_at) columns to the table. See SchemaStatements#timestamps
+ # ===== Examples
+ # t.timestamps
+ def timestamps
+ @base.add_timestamps(@table_name)
+ end
+
+ # Changes the column's definition according to the new options.
+ # See TableDefinition#column for details of the options you can use.
+ # ===== Examples
+ # t.change(:name, :string, :limit => 80)
+ # t.change(:description, :text)
+ def change(column_name, type, options = {})
+ @base.change_column(@table_name, column_name, type, options)
+ end
+
+ # Sets a new default value for a column. See
+ # ===== Examples
+ # t.change_default(:qualification, 'new')
+ # t.change_default(:authorized, 1)
+ def change_default(column_name, default)
+ @base.change_column_default(@table_name, column_name, default)
+ end
+
+ # Removes the column(s) from the table definition.
+ # ===== Examples
+ # t.remove(:qualification)
+ # t.remove(:qualification, :experience)
+ # t.removes(:qualification, :experience)
+ def remove(*column_names)
+ @base.remove_column(@table_name, column_names)
+ end
+
+ # Remove the given index from the table.
+ #
+ # Remove the suppliers_name_index in the suppliers table.
+ # t.remove_index :name
+ # Remove the index named accounts_branch_id_index in the accounts table.
+ # t.remove_index :column => :branch_id
+ # Remove the index named accounts_branch_id_party_id_index in the accounts table.
+ # t.remove_index :column => [:branch_id, :party_id]
+ # Remove the index named by_branch_party in the accounts table.
+ # t.remove_index :name => :by_branch_party
+ def remove_index(options = {})
+ @base.remove_index(@table_name, options)
+ end
+
+ # Removes the timestamp columns (created_at and updated_at) from the table.
+ # ===== Examples
+ # t.remove_timestamps
+ def remove_timestamps
+ @base.remove_timestamps(@table_name)
+ end
+
+ # Renames a column.
+ # ===== Example
+ # t.rename(:description, :name)
+ def rename(column_name, new_column_name)
+ @base.rename_column(@table_name, column_name, new_column_name)
+ end
+
+ # Adds a reference. Optionally adds a +type+ column. <tt>reference</tt>,
+ # <tt>references</tt> and <tt>belongs_to</tt> are all acceptable
+ # ===== Example
+ # t.references(:goat)
+ # t.references(:goat, :polymorphic => true)
+ # t.references(:goat)
+ # t.belongs_to(:goat)
+ def references(*args)
+ options = args.extract_options!
+ polymorphic = options.delete(:polymorphic)
+ args.each do |col|
+ @base.add_column(@table_name, "#{col}_id", :integer, options)
+ @base.add_column(@table_name, "#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) unless polymorphic.nil?
+ end
+ end
+ alias :belongs_to :references
+
+ # Adds a reference. Optionally removes a +type+ column. <tt>remove_reference</tt>,
+ # <tt>remove_references</tt> and <tt>remove_belongs_to</tt> are all acceptable
+ # ===== Example
+ # t.remove_reference(:goat)
+ # t.remove_reference(:goat, :polymorphic => true)
+ # t.remove_references(:goat)
+ # t.remove_belongs_to(:goat)
+ def remove_references(*args)
+ options = args.extract_options!
+ polymorphic = options.delete(:polymorphic)
+ args.each do |col|
+ @base.remove_column(@table_name, "#{col}_id")
+ @base.remove_column(@table_name, "#{col}_type") unless polymorphic.nil?
+ end
+ end
+ alias :remove_belongs_to :remove_references
+
+ # Adds a column or columns of a specified type
+ # ===== Example
+ # t.string(:goat)
+ # t.string(:goat, :sheep)
+ %w( string text integer float decimal datetime timestamp time date binary boolean ).each do |column_type|
+ class_eval <<-EOV
+ def #{column_type}(*args)
+ options = args.extract_options!
+ column_names = args
+
+ column_names.each do |name|
+ column = ColumnDefinition.new(@base, name, '#{column_type}')
+ if options[:limit]
+ column.limit = options[:limit]
+ elsif native['#{column_type}'.to_sym].is_a?(Hash)
+ column.limit = native['#{column_type}'.to_sym][:limit]
+ end
+ column.precision = options[:precision]
+ column.scale = options[:scale]
+ column.default = options[:default]
+ column.null = options[:null]
+ @base.add_column(@table_name, name, column.sql_type, options)
+ end
+ end
+ EOV
+ end
+
+ private
+ def native
+ @base.native_database_types
+ end
+ end
+
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
index c986f0c6f1..6aae556d67 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -45,7 +45,7 @@ module ActiveRecord
# The +options+ hash can include the following keys:
# [<tt>:id</tt>]
# Whether to automatically add a primary key column. Defaults to true.
- # Join tables for has_and_belongs_to_many should set :id => false.
+ # Join tables for +has_and_belongs_to_many+ should set <tt>:id => false</tt>.
# [<tt>:primary_key</tt>]
# The name of the primary key, if one is to be added automatically.
# Defaults to +id+.
@@ -104,6 +104,67 @@ module ActiveRecord
execute create_sql
end
+ # 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.timestamps
+ # end
+ #
+ # ====== Add a foreign key column
+ # change_table(:suppliers) do |t|
+ # t.references :company
+ # end
+ #
+ # Creates a <tt>company_id(integer)</tt> column
+ #
+ # ====== Add a polymorphic foreign key column
+ # change_table(:suppliers) do |t|
+ # t.belongs_to :company, :polymorphic => true
+ # end
+ #
+ # Creates <tt>company_type(varchar)</tt> and <tt>company_id(integer)</tt> columns
+ #
+ # ====== Remove a column
+ # change_table(:suppliers) do |t|
+ # t.remove :company
+ # end
+ #
+ # ====== Remove a column
+ # 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
+ def change_table(table_name)
+ yield Table.new(table_name, self)
+ end
+
# Renames a table.
# ===== Example
# rename_table('octopuses', 'octopi')
@@ -124,13 +185,17 @@ module ActiveRecord
execute(add_column_sql)
end
- # Removes the column from the table definition.
+ # Removes the column(s) from the table definition.
# ===== Examples
# remove_column(:suppliers, :qualification)
- def remove_column(table_name, column_name)
- execute "ALTER TABLE #{quote_table_name(table_name)} DROP #{quote_column_name(column_name)}"
+ # remove_columns(:suppliers, :qualification, :experience)
+ 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
-
+ alias :remove_columns :remove_column
+
# Changes the column's definition according to the new options.
# See TableDefinition#column for details of the options you can use.
# ===== Examples
@@ -297,7 +362,14 @@ module ActiveRecord
def add_column_options!(sql, options) #:nodoc:
sql << " DEFAULT #{quote(options[:default], options[:column])}" if options_include_default?(options)
- sql << " NOT NULL" if options[:null] == false
+ # must explcitly check for :null to allow change_column to work on migrations
+ if options.has_key? :null
+ if options[:null] == false
+ sql << " NOT NULL"
+ else
+ sql << " NULL"
+ end
+ end
end
# SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause.
diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
index 6432c3cfee..e742d60c5f 100755
--- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
@@ -196,7 +196,7 @@ module ActiveRecord
:primary_key => "int(11) DEFAULT NULL auto_increment PRIMARY KEY",
:string => { :name => "varchar", :limit => 255 },
:text => { :name => "text" },
- :integer => { :name => "int", :limit => 11 },
+ :integer => { :name => "int"},
:float => { :name => "float" },
:decimal => { :name => "decimal" },
:datetime => { :name => "datetime" },
@@ -365,7 +365,7 @@ module ActiveRecord
create_database(name)
end
- # Create a new MySQL database with optional :charset and :collation.
+ # Create a new MySQL database with optional <tt>:charset</tt> and <tt>:collation</tt>.
# Charset defaults to utf8.
#
# Example:
@@ -463,6 +463,22 @@ module ActiveRecord
execute "ALTER TABLE #{quote_table_name(table_name)} CHANGE #{quote_column_name(column_name)} #{quote_column_name(new_column_name)} #{current_type}"
end
+ # Maps logical Rails types to MySQL-specific data types.
+ def type_to_sql(type, limit = nil, precision = nil, scale = nil)
+ return super unless type.to_s == 'integer'
+
+ case limit
+ when 0..3
+ "smallint(#{limit})"
+ when 4..8
+ "int(#{limit})"
+ when 9..20
+ "bigint(#{limit})"
+ else
+ 'int(11)'
+ end
+ end
+
# SHOW VARIABLES LIKE 'name'
def show_variable(name)
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index 54b50fabd8..e3f7969cdf 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -233,7 +233,7 @@ module ActiveRecord
# * <tt>:username</tt> -- Defaults to nothing
# * <tt>:password</tt> -- Defaults to nothing
# * <tt>:database</tt> -- The name of the database. No default, must be provided.
- # * <tt>:schema_search_path</tt> -- An optional schema search path for the connection given as a string of comma-separated schema names. This is backward-compatible with the :schema_order option.
+ # * <tt>:schema_search_path</tt> -- An optional schema search path for the connection given as a string of comma-separated schema names. This is backward-compatible with the <tt>:schema_order</tt> option.
# * <tt>:encoding</tt> -- An optional client encoding that is used in a SET client_encoding TO <encoding> call on the connection.
# * <tt>:min_messages</tt> -- An optional client min messages that is used in a SET client_min_messages TO <min_messages> call on the connection.
# * <tt>:allow_concurrency</tt> -- If true, use async query methods so Ruby threads don't deadlock; otherwise, use blocking query methods.
@@ -479,9 +479,9 @@ module ActiveRecord
create_database(name)
end
- # Create a new PostgreSQL database. Options include :owner, :template,
- # :encoding, :tablespace, and :connection_limit (note that MySQL uses
- # :charset while PostgreSQL uses :encoding).
+ # Create a new PostgreSQL database. Options include <tt>:owner</tt>, <tt>:template</tt>,
+ # <tt>:encoding</tt>, <tt>:tablespace</tt>, and <tt>:connection_limit</tt> (note that MySQL uses
+ # <tt>:charset</tt> while PostgreSQL uses <tt>:encoding</tt>).
#
# Example:
# create_database config[:database], config
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
index 59a51c0279..8fa62c1845 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
@@ -219,11 +219,14 @@ module ActiveRecord
execute "VACUUM"
end
- def remove_column(table_name, column_name) #:nodoc:
- alter_table(table_name) do |definition|
- definition.columns.delete(definition[column_name])
+ def remove_column(table_name, *column_names) #:nodoc:
+ column_names.flatten.each do |column_name|
+ alter_table(table_name) do |definition|
+ definition.columns.delete(definition[column_name])
+ end
end
end
+ alias :remove_columns :remove_column
def change_column_default(table_name, column_name, default) #:nodoc:
alter_table(table_name) do |definition|