Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #4905 (closed defect: duplicate)

Opened 4 years ago

Last modified 2 years ago

[PATCH] Rails should quote table names properly (revised patch)

Reported by: xmitchx@gmail.com Assigned to: David
Priority: normal Milestone:
Component: ActiveRecord Version:
Severity: normal Keywords:
Cc:

Description

In SQL queries, mySQL specifically, if you create a table with a mysql reserved word, which is legal, then attempt to use a model, it gives errors. This is because the mySQL table needs to be backticked. A quick workaround is to use set_table_name and add backticks into the table name, but I really think Rails should do this automagically.

Attachments

mysql_adapter_backticks.diff (3.1 kB) - added by daniel@collectiveidea.com on 05/25/06 16:02:08.
Added backticks to all table references in the mysql adapter
mysql_adapter_reserved_word_table_names_patch.diff (14.9 kB) - added by gwcoffey on 09/22/07 16:55:18.
A more comprehensive patch to fix this bug, including test cases (the above patch is not valid)
mysql-failures.txt (45.1 kB) - added by mislav on 09/22/07 18:33:54.

Change History

05/25/06 15:25:33 changed by daniel@collectiveidea.com

Is there ever an instance where table names *shouldn't* have backticks?

It seems like this should be an easy fix...

05/25/06 16:02:08 changed by daniel@collectiveidea.com

  • attachment mysql_adapter_backticks.diff added.

Added backticks to all table references in the mysql adapter

05/25/06 16:24:13 changed by daniel@collectiveidea.com

  • summary changed from Rails should backtick table names automagically to [PATCH] Rails should backtick table names automagically.

I patched the adapter by adding backticks around the table name in each place.

Existing tests pass. I feel like we should have a test for "problematic" table names, but didn't implement it.

06/16/07 05:58:27 changed by jeremy2

I'm using the latest stable version of rails, and though I have not tried it out with table names, I run into the same problem with column names. It does not hurt to put backticks around table names or column names regardless. I would suggest always putting backticks around the table names and column names.

(in reply to: ↑ description ) 09/22/07 16:52:40 changed by gwcoffey

  • summary changed from [PATCH] Rails should backtick table names automagically to [PATCH] Rails should quote table names properly (revised patch).

This problem is actually three-fold. When you have a table whose name is a reserved word in MySQL (ie: 'group', 'order', 'values', etc...):

1: Migrations don't work. You also can't dump schema from an existing database that has any such tables. As far as I know, there is no workaround for this problem. This is mildly annoying in some cases, particularly when working with legacy databases.

2: Fixtures don't work. This is the biggest nuisance because my legacy database is essentially useless with fixtures, and by extension a lot of the test case niceness in rails is not available to me.

3: ActiveRecord model classes fail in numerous places. I have heard that simply doing "set_table_name 'whatever'" works around this problem, but I haven't tested it thoroughly. Since there is a workaround, this isn't a super-critical problem, but it is very possible that this workaround will break some day down the road, so it would be better for activerecord to simply work.

I have produced test cases for all three problems. I have also patched activerecord to fix the problem.

I have a few concerns I'd like feedback on:

First, the fix to migrations was relatively simple, and only required changes to the MySQL adapter. I see no reason this fix shouldn't make it into the trunk once it's been certified.

But the fix for fixtures and model classes is much deeper. I had to modify base.rb, fixtures.rb, abstract_adapter.rb, and database_statements.rb. Conceptually, I introduced a new method, AbstractAdapter#quote_table_name that returns the table name properly quoted. Every time activerecord generates SQL generically (in base.rb and fixtures.rb), it now runs the table name through this quoting process. This is similar in concept to how column names are quoted. The abstract implementation of quote_table_name simply returns the table name unchanged, so it *should* be transparent to third party adapters. Only the mysql adapter overrides this method to add table name escaping.

Since this change is deep, I think it needs to be looked at closely by someone with more knowledge of activerecord. In the worst case, I can produce a patch that only fixes Migrations and hopefully get that on the trunk sooner than later. We could then revisit the other fixes separately.

Also, this patch could affect all databases, but I have only run the mysql test suite. I don't have access to most of the additional databases to test. So the full suite of tests needs to be run and certified by someone.

PS: If this patch goes in, I think we may be able to add the same set of fixes for Microsoft SQL Server. I suspect it has the same problems, and to get it into compliance, the adapter probably just needs to override quote_table_name to return "#{table_name}". Other databases may similarly need fixes, which would all benefit from the infrastructure change.

09/22/07 16:55:18 changed by gwcoffey

  • attachment mysql_adapter_reserved_word_table_names_patch.diff added.

A more comprehensive patch to fix this bug, including test cases (the above patch is not valid)

(in reply to: ↑ description ) 09/22/07 16:57:46 changed by gwcoffey

on a side note, does any AR expert know why AbstractAdapter doesn't declare quote_column_name? This method is used on connections throughout base.rb, but the method is implemented on the individual adapters and not on the abstract base class. This seems wrong to me. If it is, I'd be glad to fix.

09/22/07 18:33:54 changed by mislav

  • attachment mysql-failures.txt added.

09/28/07 04:56:02 changed by gwcoffey

  • status changed from new to closed.
  • resolution set to duplicate.

duplicate of #4593, I enhanced that patch instead.