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.
Comment | File | Size | Author |
---|---|---|---|
#26 | 315047_quote_field_names-D6.patch | 1.19 KB | Island Usurper |
#24 | 315047-postgres-make-changefield-reserved-word-safe-2.patch | 947 bytes | Josh Waihi |
#19 | 315047-postgres-make-changefield-reserved-word-safe.patch | 954 bytes | brianV |
#1 | quote_fields_7.diff | 909 bytes | Island Usurper |
Comments
Comment #1
Island Usurper CreditAttribution: Island Usurper commentedHere's the one-line patch to Drupal HEAD. I'll post the one for Drupal 6 after this one gets approved.
Comment #2
Anonymous (not verified) CreditAttribution: Anonymous commented#371: resolve ANSI SQL-92/99/2003 reserved words conflict in query statements
Its been an issue for a while.
Comment #3
Damien Tournoud CreditAttribution: Damien Tournoud commented@earnie, I disagree. This is a much narrower issue.
Comment #4
Anonymous (not verified) CreditAttribution: Anonymous commentedNo, 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.
Comment #5
Damien Tournoud CreditAttribution: Damien Tournoud commentedThat's great because we are in a MySQL context.
Comment #6
Damien Tournoud CreditAttribution: Damien Tournoud commented@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.
Comment #7
Crell CreditAttribution: Crell commentedThis 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.
Comment #8
Anonymous (not verified) CreditAttribution: Anonymous commentedYou convinced me.
Comment #9
Crell CreditAttribution: Crell commentedLooks 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.)
Comment #10
Island Usurper CreditAttribution: Island Usurper commentedI'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.
Comment #11
Crell CreditAttribution: Crell commentedhm. 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.
Comment #12
Dries CreditAttribution: Dries commentedI committed this to CVS HEAD. I'm marking this 'active' as the PostgreSQL case needs fixing too.
Comment #13
Crell CreditAttribution: Crell commentedMarking accordingly.
Comment #14
linuxpoet CreditAttribution: linuxpoet commentedYou shouldn't have a problem with PostgreSQL and reserved words in newer versions:
type is a reserved word.
If you want to be doubly sure (and conform to standard) you could do this:
Oh and BTW don't be fooled, lots of people use Drupal + PostgreSQL.
Comment #15
Crell CreditAttribution: Crell commented@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.
Comment #16
nigel CreditAttribution: nigel commentedPostgres 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)
Comment #17
Crell CreditAttribution: Crell commentedOK, 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?
Comment #18
Anonymous (not verified) CreditAttribution: Anonymous commentedNo it would be the double quote " instead. The double quote character is the ANSI defined quoting character for tables and fields.
Comment #19
brianV CreditAttribution: brianV commentedPatch 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.
Comment #21
brianV CreditAttribution: brianV commentedSetting to 'needs review' - testbot was broken.
Comment #23
Shiny CreditAttribution: Shiny commentedtagging for next Postgres Code Sprint
Comment #24
Josh Waihi CreditAttribution: Josh Waihi commentedadding 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
Comment #25
webchickCommitted to HEAD. Thanks.
Comment #26
Island Usurper CreditAttribution: Island Usurper commentedThanks, everyone, for looking into this. Here's an equivalent patch for Drupal 6, for both MySQL and Postgres.
Comment #27
Island Usurper CreditAttribution: Island Usurper commentedUntag pgsql specificity.
Comment #28
brianV CreditAttribution: brianV commentedIsland Usurper's patch in #26 is good. RTBC.
Comment #29
Gábor HojtsyCommitted to Drupal 6 too, thanks.
Comment #31
jason_purdy CreditAttribution: jason_purdy commentedI 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:
Results in this output and the field not being changed:
Comment #32
Anonymous (not verified) CreditAttribution: Anonymous commentedPlease 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.
Comment #33
jason_purdy CreditAttribution: jason_purdy commentedSorry about that ... I figured it would be better organized for my query to appear with the same bug.
Thanks!