1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Add an :if_not_exists option to create_table

[fatkodima & Stefan Kanev]
This commit is contained in:
fatkodima 2017-12-09 18:02:51 +02:00 committed by fatkodima
parent 7f7e7e8b39
commit 6e0ff00537
5 changed files with 59 additions and 4 deletions

View file

@ -1,3 +1,22 @@
* Add an `:if_not_exists` option to `create_table`.
Example:
create_table :posts, if_not_exists: true do |t|
t.string :title
end
That would execute:
CREATE TABLE IF NOT EXISTS posts (
...
)
If the table already exists, `if_not_exists: false` (the default) raises an
exception whereas `if_not_exists: true` does nothing.
*fatkodima*, *Stefan Kanev*
* Defining an Enum as a Hash with blank key, or as an Array with a blank value, now raises an `ArgumentError`.
*Christophe Maximin*

View file

@ -39,7 +39,9 @@ module ActiveRecord
end
def visit_TableDefinition(o)
create_sql = +"CREATE#{' TEMPORARY' if o.temporary} TABLE #{quote_table_name(o.name)} "
create_sql = +"CREATE#{' TEMPORARY' if o.temporary} TABLE "
create_sql << "IF NOT EXISTS " if o.if_not_exists
create_sql << "#{quote_table_name(o.name)} "
statements = o.columns.map { |c| accept c }
statements << accept(o.primary_keys) if o.primary_keys

View file

@ -257,14 +257,15 @@ module ActiveRecord
include ColumnMethods
attr_accessor :indexes
attr_reader :name, :temporary, :options, :as, :foreign_keys, :comment
attr_reader :name, :temporary, :if_not_exists, :options, :as, :foreign_keys, :comment
def initialize(name, temporary = false, options = nil, as = nil, comment: nil)
def initialize(name, temporary = false, if_not_exists = false, options = nil, as = nil, comment: nil)
@columns_hash = {}
@indexes = []
@foreign_keys = []
@primary_keys = nil
@temporary = temporary
@if_not_exists = if_not_exists
@options = options
@as = as
@name = name

View file

@ -205,6 +205,9 @@ module ActiveRecord
# Set to true to drop the table before creating it.
# Set to +:cascade+ to drop dependent objects as well.
# Defaults to false.
# [<tt>:if_not_exists</tt>]
# Set to true to avoid raising an error when the table already exists.
# Defaults to false.
# [<tt>:as</tt>]
# SQL to use to generate the table. When this option is used, the block is
# ignored, as are the <tt>:id</tt> and <tt>:primary_key</tt> options.
@ -288,7 +291,7 @@ module ActiveRecord
#
# See also TableDefinition#column for details on how to create columns.
def create_table(table_name, comment: nil, **options)
td = create_table_definition table_name, options[:temporary], options[:options], options[:as], comment: comment
td = create_table_definition table_name, options[:temporary], options[:if_not_exists], options[:options], options[:as], comment: comment
if options[:id] != false && !options[:as]
pk = options.fetch(:primary_key) do

View file

@ -127,6 +127,36 @@ class MigrationTest < ActiveRecord::TestCase
assert_equal 20131219224947, migrator.current_version
end
def test_create_table_raises_if_already_exists
connection = Person.connection
connection.create_table :testings, force: true do |t|
t.string :foo
end
assert_raise(ActiveRecord::StatementInvalid) do
connection.create_table :testings do |t|
t.string :foo
end
end
ensure
connection.drop_table :testings, if_exists: true
end
def test_create_table_with_if_not_exists_true
connection = Person.connection
connection.create_table :testings, force: true do |t|
t.string :foo
end
assert_nothing_raised do
connection.create_table :testings, if_not_exists: true do |t|
t.string :foo
end
end
ensure
connection.drop_table :testings, if_exists: true
end
def test_create_table_with_force_true_does_not_drop_nonexisting_table
# using a copy as we need the drop_table method to
# continue to work for the ensure block of the test