So, I admit that using reserved words for column names was a big mistake, but it was a typo, and I didn't know I had made it.

The gist of the bug is that db_change_field() uses backticks (`) to escape the new column name, but not the old column name. Since the column name is escaped when it is first created in drupal_install_schema(), it will gladly create a column that is a reserved word, but you can't change it after that.

Since using reserved words is an error, I'd like to change that column in an update function. But I can't.

Note that this issue is present in HEAD as well as D6.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Island Usurper’s picture

Version: 6.x-dev » 7.x-dev
Status: Active » Needs review
FileSize
909 bytes

Here's the one-line patch to Drupal HEAD. I'll post the one for Drupal 6 after this one gets approved.

Anonymous’s picture

Status: Needs review » Closed (duplicate)
Damien Tournoud’s picture

Title: MySQL: can't update fields named with reserved words » All schema API operations should be reserved-word safe
Status: Closed (duplicate) » Active

@earnie, I disagree. This is a much narrower issue.

Anonymous’s picture

Status: Active » Closed (duplicate)

No, it isn't. Take a look at the patch. You'll find similar patches in the issue I pointed to. And we can't quote with ` because ` is MySql only.

Damien Tournoud’s picture

Status: Closed (duplicate) » Active

And we can't quote with ` because ` is MySql only.

That's great because we are in a MySQL context.

Damien Tournoud’s picture

@earnie: it seems that we are taking the "don't use any of the reserved-words of any database engine and battle to change them if the list evolves" route. If we do, we have *no other choice* than to make *all* schema API operations reserved-word safe, because if we don't, we will not be able (as the original poster) to change the name of any column that uses a reserved word.

Crell’s picture

Status: Active » Needs review

This is actually a prerequisite for fixing the use of reserved words, since we can't fix the problem otherwise. So this issue is valid, the other should be marked "postponed".

Visually the patch looks fine, but I need to try applying it and testing it first. I'll try to get to that soon.

Anonymous’s picture

You convinced me.

Crell’s picture

Status: Needs review » Needs work

Looks fine, applies fine. There's no Schema API unit tests yet, sadly, but this is trivial enough that I'm confident that it breaks nothing.

However, this only addresses MySQL. Can we give Postgres some love? (It is still a supported database, even if no one uses it.) Or should we push that off to a separate patch? (webchick/Dries, your call, given how lackluster Postgres interest is.)

Island Usurper’s picture

I'm not sure that Postgres is affected the same way by the bug. None of its specific Schema API functions appear to do anything with escaping reserved words in column names. (How would Postgres do that? Double quotes?)

Would it actually be better to restore symmetry in the other direction, as in removing the backticks? From my point of view, I would have been better off if I hadn't been allowed to make the mistake of creating a field called "values". But I don't know how that would affect core, or indeed, the rest of contrib.

Crell’s picture

Status: Needs work » Reviewed & tested by the community

hm. I don't know Postgres well enough to know either way, and we're still lacking good schema API code coverage on unit tests to check it. (And I am scheming to rewrite Schema API anyway).

Given that there are reserved word columns in core now, and we will need Schema API to support them in order to convert away from them, we can't simply ignore the problem.

I think I'm actually going to push this up to RTBC. Committers, if you really want Postgres checked/fixed as part of this patch, find me a Postgres person who can. :-) Otherwise let's get MySQL taken care of and fix Postgres (if needed) separately.

Dries’s picture

Priority: Normal » Critical
Status: Reviewed & tested by the community » Active

I committed this to CVS HEAD. I'm marking this 'active' as the PostgreSQL case needs fixing too.

Crell’s picture

Title: All schema API operations should be reserved-word safe » Postgres: All schema API operations should be reserved-word safe

Marking accordingly.

linuxpoet’s picture

You shouldn't have a problem with PostgreSQL and reserved words in newer versions:

postgres=# \d type_test;
 Table "public.type_test"
 Column | Type | Modifiers 
--------+------+-----------
 type   | text | 

type is a reserved word.

postgres=# select type from type_test;
 type 
------
(0 rows)

If you want to be doubly sure (and conform to standard) you could do this:

postgres=# select "type" from type_test;
 type 
------
(0 rows)

Oh and BTW don't be fooled, lots of people use Drupal + PostgreSQL.

Crell’s picture

@linuxpoet: So the postgres driver is safe as-is, and doesn't need any more work? If so, let's mark this fixed. Or we can add " in the schema operations like we do ` for MySQL. Whichever you think is safer.

nigel’s picture

Postgres will still complain if you use certain reserved words - GROUP comes to mind as an example:

postgres=# select group from mytable;
ERROR: syntax error at or near "group"
LINE 1: select group from mytable;
^
postgres=# select version();
version
----------------------------------------------------------------------------------
PostgreSQL 8.3.3 on i486-pc-linux-gnu, compiled by GCC cc (Debian 4.3.1-1) 4.3.1
(1 row)

Crell’s picture

OK, so we need to quote fields in postgres, too. Is ' (apostrophe) the right character for that? If so, can you roll a quick patch a la the MySQL one above?

Anonymous’s picture

No it would be the double quote " instead. The double quote character is the ANSI defined quoting character for tables and fields.

brianV’s picture

Status: Active » Needs review
FileSize
954 bytes

Patch rolled for Postgres following earnie's suggestion that the double quote is the proper escaping character.

I only wrapped them around the name of the existing field, and not the new field to stay in sync with the MySQL patch above.

Status: Needs review » Needs work

The last submitted patch failed testing.

brianV’s picture

Status: Needs work » Needs review

Setting to 'needs review' - testbot was broken.

Status: Needs review » Needs work

The last submitted patch failed testing.

Shiny’s picture

Issue tags: +PostgreSQL Code Sprint

tagging for next Postgres Code Sprint

Josh Waihi’s picture

Status: Needs work » Reviewed & tested by the community
Issue tags: +Quick fix
FileSize
947 bytes

adding double quotes around the renamed old field. Doesn't hurt. Testbot shouldn't fail, it doesn't test PostgreSQL (yet), this is a no brainer to comit

webchick’s picture

Status: Reviewed & tested by the community » Fixed

Committed to HEAD. Thanks.

Island Usurper’s picture

Title: Postgres: All schema API operations should be reserved-word safe » All schema API operations should be reserved-word safe
Version: 7.x-dev » 6.x-dev
Status: Fixed » Needs review
FileSize
1.19 KB

Thanks, everyone, for looking into this. Here's an equivalent patch for Drupal 6, for both MySQL and Postgres.

Island Usurper’s picture

Issue tags: -PostgreSQL Code Sprint

Untag pgsql specificity.

brianV’s picture

Status: Needs review » Reviewed & tested by the community

Island Usurper's patch in #26 is good. RTBC.

Gábor Hojtsy’s picture

Status: Reviewed & tested by the community » Fixed

Committed to Drupal 6 too, thanks.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

jason_purdy’s picture

Version: 6.x-dev » 6.25
Status: Closed (fixed) » Active

I came across another instance of this bug w/ Drupal 6.25 when using a reserved word (version) and trying to add an index at the same time. Here's my code in my module's update hook:

  db_change_field( $ret, 'rmgt_subscription', 'version', 'version', array(
    'type' => 'varchar',
    'length' => 50,
    'default' => 'print',
    'not null' => TRUE,
  ), array( 'indexes' => array( 'by_version' => array( array( 'version', 10 ) ) ) ) );

Results in this output and the field not being changed:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use [warning]
near 'version(10))' at line 1
query: ALTER TABLE rmgt_subscription CHANGE `version` `version` VARCHAR(50) NOT NULL DEFAULT 'print', ADD INDEX
by_version (version(10)) database.mysqli.inc:169

Anonymous’s picture

Version: 6.25 » 6.x-dev
Status: Active » Closed (fixed)

Please do not reopen 3 year old issues. D6 is in security patch mode only so unless this is a security issue, which I don't believe it is, then it will not get fixed. A work around for the problem is to change

array( 'indexes' => array( 'by_version' => array( array( 'version', 10 ) ) ) )

to

array( 'indexes' => array( 'by_version' => array( array( '`version`', 10 ) ) ) )

assuming MySQL.

jason_purdy’s picture

Sorry about that ... I figured it would be better organized for my query to appear with the same bug.

Thanks!