Permalink
Browse files

SQLite, MySQL, PostgreSQL, Oracle: quote column names in column migra…

…tion SQL statements. Closes #8466.

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@6889 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
1 parent 8139de2 commit 69e4cc6e316b1ee9fbd5260103cb5f7f50643d62 @jeremy jeremy committed May 29, 2007
@@ -1,5 +1,7 @@
*SVN*
+* SQLite, MySQL, PostgreSQL, Oracle: quote column names in column migration SQL statements. #8466 [marclove, lorenjohnson]
+
* Allow nil serialized attributes with a set class constraint. #7293 [sandofsky]
* Oracle: support binary fixtures. #7987 [Michael Schoen]
@@ -388,22 +388,22 @@ def rename_table(name, new_name)
def change_column_default(table_name, column_name, default) #:nodoc:
current_type = select_one("SHOW COLUMNS FROM #{table_name} LIKE '#{column_name}'")["Type"]
- execute("ALTER TABLE #{table_name} CHANGE #{column_name} #{column_name} #{current_type} DEFAULT #{quote(default)}")
+ execute("ALTER TABLE #{table_name} CHANGE #{quote_column_name(column_name)} #{quote_column_name(column_name)} #{current_type} DEFAULT #{quote(default)}")
end
def change_column(table_name, column_name, type, options = {}) #:nodoc:
unless options_include_default?(options)
options[:default] = select_one("SHOW COLUMNS FROM #{table_name} LIKE '#{column_name}'")["Default"]
end
- change_column_sql = "ALTER TABLE #{table_name} CHANGE #{column_name} #{column_name} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
+ change_column_sql = "ALTER TABLE #{table_name} CHANGE #{quote_column_name(column_name)} #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
add_column_options!(change_column_sql, options)
execute(change_column_sql)
end
def rename_column(table_name, column_name, new_column_name) #:nodoc:
current_type = select_one("SHOW COLUMNS FROM #{table_name} LIKE '#{column_name}'")["Type"]
- execute "ALTER TABLE #{table_name} CHANGE #{column_name} #{new_column_name} #{current_type}"
+ execute "ALTER TABLE #{table_name} CHANGE #{quote_column_name(column_name)} #{quote_column_name(new_column_name)} #{current_type}"
end
@@ -387,21 +387,21 @@ def remove_index(table_name, options = {}) #:nodoc:
end
def change_column_default(table_name, column_name, default) #:nodoc:
- execute "ALTER TABLE #{table_name} MODIFY #{column_name} DEFAULT #{quote(default)}"
+ execute "ALTER TABLE #{table_name} MODIFY #{quote_column_name(column_name)} DEFAULT #{quote(default)}"
end
def change_column(table_name, column_name, type, options = {}) #:nodoc:
- change_column_sql = "ALTER TABLE #{table_name} MODIFY #{column_name} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
+ change_column_sql = "ALTER TABLE #{table_name} MODIFY #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
add_column_options!(change_column_sql, options)
execute(change_column_sql)
end
def rename_column(table_name, column_name, new_column_name) #:nodoc:
- execute "ALTER TABLE #{table_name} RENAME COLUMN #{column_name} to #{new_column_name}"
+ execute "ALTER TABLE #{table_name} RENAME COLUMN #{quote_column_name(column_name)} to #{new_column_name}"
end
def remove_column(table_name, column_name) #:nodoc:
- execute "ALTER TABLE #{table_name} DROP COLUMN #{column_name}"
+ execute "ALTER TABLE #{table_name} DROP COLUMN #{quote_column_name(column_name)}"
end
# Find a table's primary key and sequence.
@@ -325,32 +325,35 @@ def add_column(table_name, column_name, type, options = {})
default = options[:default]
notnull = options[:null] == false
+ quoted_column_name = quote_column_name(column_name)
+
# Add the column.
- execute("ALTER TABLE #{table_name} ADD COLUMN #{column_name} #{type_to_sql(type, options[:limit])}")
+ execute("ALTER TABLE #{table_name} ADD COLUMN #{quoted_column_name} #{type_to_sql(type, options[:limit])}")
# Set optional default. If not null, update nulls to the new default.
if options_include_default?(options)
change_column_default(table_name, column_name, default)
if notnull
- execute("UPDATE #{table_name} SET #{column_name}=#{quote(default, options[:column])} WHERE #{column_name} IS NULL")
+ execute("UPDATE #{table_name} SET #{quoted_column_name}=#{quote(default, options[:column])} WHERE #{quoted_column_name} IS NULL")
end
end
if notnull
- execute("ALTER TABLE #{table_name} ALTER #{column_name} SET NOT NULL")
+ execute("ALTER TABLE #{table_name} ALTER #{quoted_column_name} SET NOT NULL")
end
end
def change_column(table_name, column_name, type, options = {}) #:nodoc:
begin
- execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} TYPE #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
+ execute "ALTER TABLE #{table_name} ALTER COLUMN #{quoted_column_name} TYPE #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
rescue ActiveRecord::StatementInvalid
# This is PG7, so we use a more arcane way of doing it.
begin_db_transaction
- add_column(table_name, "#{column_name}_ar_tmp", type, options)
- execute "UPDATE #{table_name} SET #{column_name}_ar_tmp = CAST(#{column_name} AS #{type_to_sql(type, options[:limit], options[:precision], options[:scale])})"
+ tmp_column_name = "#{column_name}_ar_tmp"
+ add_column(table_name, tmp_column_name, type, options)
+ execute "UPDATE #{table_name} SET #{quote_column_name(tmp_column_name)} = CAST(#{quote_column_name(column_name)} AS #{type_to_sql(type, options[:limit], options[:precision], options[:scale])})"
remove_column(table_name, column_name)
- rename_column(table_name, "#{column_name}_ar_tmp", column_name)
+ rename_column(table_name, tmp_column_name, column_name)
commit_db_transaction
end
@@ -327,8 +327,10 @@ def copy_table_contents(from, to, columns, rename = {}) #:nodoc:
rename.inject(column_mappings) {|map, a| map[a.last] = a.first; map}
from_columns = columns(from).collect {|col| col.name}
columns = columns.find_all{|col| from_columns.include?(column_mappings[col])}
+ quoted_columns = columns.map { |col| quote_column_name(col) } * ','
+
@connection.execute "SELECT * FROM #{from}" do |row|
- sql = "INSERT INTO #{to} ("+columns*','+") VALUES ("
+ sql = "INSERT INTO #{to} (#{quoted_columns}) VALUES ("
sql << columns.map {|col| quote row[column_mappings[col]]} * ', '
sql << ')'
@connection.execute sql
@@ -398,6 +398,17 @@ def test_rename_column
end
end
+ def test_rename_column_with_sql_reserved_word
+ begin
+ assert_nothing_raised { Person.connection.rename_column "people", "first_name", "group" }
+ Person.reset_column_information
+ assert Person.column_names.include?("group")
+ ensure
+ Person.connection.remove_column("people", "group") rescue nil
+ Person.connection.add_column("people", "first_name", :string) rescue nil
+ end
+ end
+
def test_rename_table
begin
ActiveRecord::Base.connection.create_table :octopuses do |t|

0 comments on commit 69e4cc6

Please sign in to comment.