Changeset 7932
- Timestamp:
- 10/16/07 05:06:33 (2 years ago)
- Files:
-
- trunk/activerecord/CHANGELOG (modified) (1 diff)
- trunk/activerecord/lib/active_record/base.rb (modified) (10 diffs)
- trunk/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb (modified) (1 diff)
- trunk/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb (modified) (1 diff)
- trunk/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb (modified) (1 diff)
- trunk/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb (modified) (7 diffs)
- trunk/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb (modified) (7 diffs)
- trunk/activerecord/lib/active_record/fixtures.rb (modified) (1 diff)
- trunk/activerecord/test/active_schema_test_mysql.rb (modified) (2 diffs)
- trunk/activerecord/test/fixtures/reserved_words (added)
- trunk/activerecord/test/fixtures/reserved_words/distinct.yml (added)
- trunk/activerecord/test/fixtures/reserved_words/distincts_selects.yml (added)
- trunk/activerecord/test/fixtures/reserved_words/group.yml (added)
- trunk/activerecord/test/fixtures/reserved_words/select.yml (added)
- trunk/activerecord/test/fixtures/reserved_words/values.yml (added)
- trunk/activerecord/test/reserved_word_test_mysql.rb (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/activerecord/CHANGELOG
r7913 r7932 1 1 *SVN* 2 3 * Quote table names. Defaults to column quoting. #4593 [Justin Lynn, gwcoffey, eadz, Dmitry V. Sabanin, Jeremy Kemper] 2 4 3 5 * Alias association #build to #new so it behaves predictably. #8787 [lifofifo] trunk/activerecord/lib/active_record/base.rb
r7908 r7932 532 532 # Post.delete_all "person_id = 5 AND (category = 'Something' OR category = 'Else')" 533 533 def delete_all(conditions = nil) 534 sql = "DELETE FROM #{ table_name} "534 sql = "DELETE FROM #{quoted_table_name} " 535 535 add_conditions!(sql, conditions, scope(:find)) 536 536 connection.delete(sql, "#{name} Delete all") … … 1034 1034 def find_one(id, options) 1035 1035 conditions = " AND (#{sanitize_sql(options[:conditions])})" if options[:conditions] 1036 options.update :conditions => "#{ table_name}.#{connection.quote_column_name(primary_key)} = #{quote_value(id,columns_hash[primary_key])}#{conditions}"1036 options.update :conditions => "#{quoted_table_name}.#{connection.quote_column_name(primary_key)} = #{quote_value(id,columns_hash[primary_key])}#{conditions}" 1037 1037 1038 1038 # Use find_every(options).first since the primary key condition … … 1049 1049 conditions = " AND (#{sanitize_sql(options[:conditions])})" if options[:conditions] 1050 1050 ids_list = ids.map { |id| quote_value(id,columns_hash[primary_key]) }.join(',') 1051 options.update :conditions => "#{ table_name}.#{connection.quote_column_name(primary_key)} IN (#{ids_list})#{conditions}"1051 options.update :conditions => "#{quoted_table_name}.#{connection.quote_column_name(primary_key)} IN (#{ids_list})#{conditions}" 1052 1052 1053 1053 result = find_every(options) … … 1127 1127 def construct_finder_sql(options) 1128 1128 scope = scope(:find) 1129 sql = "SELECT #{(scope && scope[:select]) || options[:select] || (options[:joins] && table_name + '.*') || '*'} "1130 sql << "FROM #{(scope && scope[:from]) || options[:from] || table_name} "1129 sql = "SELECT #{(scope && scope[:select]) || options[:select] || (options[:joins] && quoted_table_name + '.*') || '*'} " 1130 sql << "FROM #{(scope && scope[:from]) || options[:from] || quoted_table_name} " 1131 1131 1132 1132 add_joins!(sql, options, scope) … … 1221 1221 def type_condition 1222 1222 quoted_inheritance_column = connection.quote_column_name(inheritance_column) 1223 type_condition = subclasses.inject("#{ table_name}.#{quoted_inheritance_column} = '#{name.demodulize}' ") do |condition, subclass|1224 condition << "OR #{ table_name}.#{quoted_inheritance_column} = '#{subclass.name.demodulize}' "1223 type_condition = subclasses.inject("#{quoted_table_name}.#{quoted_inheritance_column} = '#{name.demodulize}' ") do |condition, subclass| 1224 condition << "OR #{quoted_table_name}.#{quoted_inheritance_column} = '#{subclass.name.demodulize}' " 1225 1225 end 1226 1226 … … 1573 1573 def sanitize_sql_hash_for_conditions(attrs) 1574 1574 conditions = attrs.map do |attr, value| 1575 "#{ table_name}.#{connection.quote_column_name(attr)} #{attribute_condition(value)}"1575 "#{quoted_table_name}.#{connection.quote_column_name(attr)} #{attribute_condition(value)}" 1576 1576 end.join(' AND ') 1577 1577 … … 1743 1743 unless new_record? 1744 1744 connection.delete <<-end_sql, "#{self.class.name} Destroy" 1745 DELETE FROM #{self.class. table_name}1745 DELETE FROM #{self.class.quoted_table_name} 1746 1746 WHERE #{connection.quote_column_name(self.class.primary_key)} = #{quoted_id} 1747 1747 end_sql … … 1987 1987 return 0 if quoted_attributes.empty? 1988 1988 connection.update( 1989 "UPDATE #{self.class. table_name} " +1989 "UPDATE #{self.class.quoted_table_name} " + 1990 1990 "SET #{quoted_comma_pair_list(connection, quoted_attributes)} " + 1991 1991 "WHERE #{connection.quote_column_name(self.class.primary_key)} = #{quote_value(id)}", … … 2006 2006 connection.empty_insert_statement(self.class.table_name) 2007 2007 else 2008 "INSERT INTO #{self.class. table_name} " +2008 "INSERT INTO #{self.class.quoted_table_name} " + 2009 2009 "(#{quoted_column_names.join(', ')}) " + 2010 2010 "VALUES(#{quoted_attributes.values.join(', ')})" … … 2181 2181 end 2182 2182 2183 def self.quoted_table_name 2184 self.connection.quote_table_name(self.table_name) 2185 end 2186 2183 2187 def quote_columns(quoter, hash) 2184 2188 hash.inject({}) do |quoted, (name, value)| trunk/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
r7666 r7932 64 64 end 65 65 66 # QUOTING ================================================== 67 68 # Override to return the quoted table name if the database needs it 69 def quote_table_name(name) 70 name 71 end 66 72 67 73 # CONNECTION MANAGEMENT ==================================== trunk/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
r7753 r7932 137 137 # something beyond a simple insert (eg. Oracle). 138 138 def insert_fixture(fixture, table_name) 139 execute "INSERT INTO #{ table_name} (#{fixture.key_list}) VALUES (#{fixture.value_list})", 'Fixture Insert'139 execute "INSERT INTO #{quote_table_name(table_name)} (#{fixture.key_list}) VALUES (#{fixture.value_list})", 'Fixture Insert' 140 140 end 141 141 142 142 def empty_insert_statement(table_name) 143 "INSERT INTO #{ table_name} VALUES(DEFAULT)"143 "INSERT INTO #{quote_table_name(table_name)} VALUES(DEFAULT)" 144 144 end 145 145 trunk/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
r7329 r7932 40 40 end 41 41 42 # Returns a quoted form of the column name. This is highly adapter 43 # specific. 44 def quote_column_name(name) 45 name 42 # Quotes the column name. Defaults to no quoting. 43 def quote_column_name(column_name) 44 column_name 45 end 46 47 # Quotes the table name. Defaults to column name quoting. 48 def quote_table_name(table_name) 49 quote_column_name(table_name) 46 50 end 47 51 trunk/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
r7931 r7932 88 88 # 89 89 # See also TableDefinition#column for details on how to create columns. 90 def create_table( name, options = {})90 def create_table(table_name, options = {}) 91 91 table_definition = TableDefinition.new(self) 92 92 table_definition.primary_key(options[:primary_key] || "id") unless options[:id] == false … … 95 95 96 96 if options[:force] 97 drop_table( name, options) rescue nil97 drop_table(table_name, options) rescue nil 98 98 end 99 99 100 100 create_sql = "CREATE#{' TEMPORARY' if options[:temporary]} TABLE " 101 create_sql << "#{ name} ("101 create_sql << "#{quote_table_name(table_name)} (" 102 102 create_sql << table_definition.to_sql 103 103 create_sql << ") #{options[:options]}" 104 104 execute create_sql 105 105 end 106 106 107 107 # Renames a table. 108 108 # ===== Example 109 109 # rename_table('octopuses', 'octopi') 110 def rename_table( name, new_name)110 def rename_table(table_name, new_name) 111 111 raise NotImplementedError, "rename_table is not implemented" 112 112 end 113 113 114 114 # Drops a table from the database. 115 def drop_table( name, options = {})116 execute "DROP TABLE #{ name}"115 def drop_table(table_name, options = {}) 116 execute "DROP TABLE #{quote_table_name(table_name)}" 117 117 end 118 118 … … 120 120 # See TableDefinition#column for details of the options you can use. 121 121 def add_column(table_name, column_name, type, options = {}) 122 add_column_sql = "ALTER TABLE #{ table_name} ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"122 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])}" 123 123 add_column_options!(add_column_sql, options) 124 124 execute(add_column_sql) … … 129 129 # remove_column(:suppliers, :qualification) 130 130 def remove_column(table_name, column_name) 131 execute "ALTER TABLE #{ table_name} DROP #{quote_column_name(column_name)}"131 execute "ALTER TABLE #{quote_table_name(table_name)} DROP #{quote_column_name(column_name)}" 132 132 end 133 133 … … 195 195 end 196 196 quoted_column_names = column_names.map { |e| quote_column_name(e) }.join(", ") 197 execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{ table_name} (#{quoted_column_names})"197 execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names})" 198 198 end 199 199 … … 235 235 def initialize_schema_information 236 236 begin 237 execute "CREATE TABLE #{ ActiveRecord::Migrator.schema_info_table_name} (version #{type_to_sql(:integer)})"238 execute "INSERT INTO #{ ActiveRecord::Migrator.schema_info_table_name} (version) VALUES(0)"237 execute "CREATE TABLE #{quote_table_name(ActiveRecord::Migrator.schema_info_table_name)} (version #{type_to_sql(:integer)})" 238 execute "INSERT INTO #{quote_table_name(ActiveRecord::Migrator.schema_info_table_name)} (version) VALUES(0)" 239 239 rescue ActiveRecord::StatementInvalid 240 240 # Schema has been initialized … … 245 245 begin 246 246 if (current_schema = ActiveRecord::Migrator.current_version) > 0 247 return "INSERT INTO #{ ActiveRecord::Migrator.schema_info_table_name} (version) VALUES (#{current_schema})"247 return "INSERT INTO #{quote_table_name(ActiveRecord::Migrator.schema_info_table_name)} (version) VALUES (#{current_schema})" 248 248 end 249 249 rescue ActiveRecord::StatementInvalid trunk/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
r7790 r7932 209 209 end 210 210 211 def quote_table_name(name) #:nodoc: 212 quote_column_name(name) 213 end 214 211 215 def quote_string(string) #:nodoc: 212 216 @connection.quote(string) … … 323 327 select_all(sql).inject("") do |structure, table| 324 328 table.delete('Table_type') 325 structure += select_one("SHOW CREATE TABLE #{ table.to_a.first.last}")["Create Table"] + ";\n\n"329 structure += select_one("SHOW CREATE TABLE #{quote_table_name(table.to_a.first.last)}")["Create Table"] + ";\n\n" 326 330 end 327 331 end … … 371 375 end 372 376 377 def drop_table(table_name, options = {}) 378 super(table_name, options) 379 end 380 373 381 def indexes(table_name, name = nil)#:nodoc: 374 382 indexes = [] 375 383 current_index = nil 376 execute("SHOW KEYS FROM #{ table_name}", name).each do |row|384 execute("SHOW KEYS FROM #{quote_table_name(table_name)}", name).each do |row| 377 385 if current_index != row[2] 378 386 next if row[2] == "PRIMARY" # skip the primary key … … 387 395 388 396 def columns(table_name, name = nil)#:nodoc: 389 sql = "SHOW FIELDS FROM #{ table_name}"397 sql = "SHOW FIELDS FROM #{quote_table_name(table_name)}" 390 398 columns = [] 391 399 execute(sql, name).each { |field| columns << MysqlColumn.new(field[0], field[4], field[1], field[2] == "YES") } … … 393 401 end 394 402 395 def create_table( name, options = {}) #:nodoc:396 super( name, {:options => "ENGINE=InnoDB"}.merge(options))397 end 398 399 def rename_table( name, new_name)400 execute "RENAME TABLE #{ name} TO #{new_name}"403 def create_table(table_name, options = {}) #:nodoc: 404 super(table_name, options.reverse_merge(:options => "ENGINE=InnoDB")) 405 end 406 407 def rename_table(table_name, new_name) 408 execute "RENAME TABLE #{quote_table_name(table_name)} TO #{quote_table_name(new_name)}" 401 409 end 402 410 403 411 def change_column_default(table_name, column_name, default) #:nodoc: 404 current_type = select_one("SHOW COLUMNS FROM #{ table_name} LIKE '#{column_name}'")["Type"]405 406 execute("ALTER TABLE #{ table_name} CHANGE #{quote_column_name(column_name)} #{quote_column_name(column_name)} #{current_type} DEFAULT #{quote(default)}")412 current_type = select_one("SHOW COLUMNS FROM #{quote_table_name(table_name)} LIKE '#{column_name}'")["Type"] 413 414 execute("ALTER TABLE #{quote_table_name(table_name)} CHANGE #{quote_column_name(column_name)} #{quote_column_name(column_name)} #{current_type} DEFAULT #{quote(default)}") 407 415 end 408 416 … … 416 424 end 417 425 418 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])}"426 change_column_sql = "ALTER TABLE #{quote_table_name(table_name)} CHANGE #{quote_column_name(column_name)} #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}" 419 427 add_column_options!(change_column_sql, options) 420 428 execute(change_column_sql) … … 422 430 423 431 def rename_column(table_name, column_name, new_column_name) #:nodoc: 424 current_type = select_one("SHOW COLUMNS FROM #{ table_name} LIKE '#{column_name}'")["Type"]425 execute "ALTER TABLE #{ table_name} CHANGE #{quote_column_name(column_name)} #{quote_column_name(new_column_name)} #{current_type}"432 current_type = select_one("SHOW COLUMNS FROM #{quote_table_name(table_name)} LIKE '#{column_name}'")["Type"] 433 execute "ALTER TABLE #{quote_table_name(table_name)} CHANGE #{quote_column_name(column_name)} #{quote_column_name(new_column_name)} #{current_type}" 426 434 end 427 435 trunk/activerecord/lib/active_record/fixtures.rb
r7667 r7932 319 319 320 320 def delete_existing_fixtures 321 @connection.delete "DELETE FROM #{@ table_name}", 'Fixture Delete'321 @connection.delete "DELETE FROM #{@connection.quote_table_name(table_name)}", 'Fixture Delete' 322 322 end 323 323 trunk/activerecord/test/active_schema_test_mysql.rb
r6848 r7932 14 14 15 15 def test_drop_table 16 assert_equal "DROP TABLE people", drop_table(:people)16 assert_equal "DROP TABLE `people`", drop_table(:people) 17 17 end 18 18 … … 26 26 27 27 def test_add_column 28 assert_equal "ALTER TABLE peopleADD `last_name` varchar(255)", add_column(:people, :last_name, :string)28 assert_equal "ALTER TABLE `people` ADD `last_name` varchar(255)", add_column(:people, :last_name, :string) 29 29 end 30 30 31 31 def test_add_column_with_limit 32 assert_equal "ALTER TABLE peopleADD `key` varchar(32)", add_column(:people, :key, :string, :limit => 32)32 assert_equal "ALTER TABLE `people` ADD `key` varchar(32)", add_column(:people, :key, :string, :limit => 32) 33 33 end 34 34