Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
A very common mysql technique for joining against a table in an external DB is to prefix the table with the name of the DB. This technique does not work in DBTNG because it strips period from table names. An example of such a query is SELECT * FROM users u JOIN external.sales e ON u.uid=e.uid
This patch allows period for mysql tables. Other engines are unaffected.
Comment | File | Size | Author |
---|---|---|---|
#8 | escapeTable.diff | 461 bytes | moshe weitzman |
escapeTable.diff | 713 bytes | moshe weitzman | |
Comments
Comment #1
chx CreditAttribution: chx commentedLooks good to me. Can't imagine why a dot would hurt other DBs but this way we know what we are doing.
Comment #2
Damien Tournoud CreditAttribution: Damien Tournoud commentedThat will fail horribly if there is a default prefix. Not sure how to workaround that.
Comment #3
Crell CreditAttribution: Crell commentedHow is this different than #302327: Support cross-schema/database prefixing like we claim to?
Comment #4
moshe weitzman CreditAttribution: moshe weitzman commentedRetitle to reflect the intent here. I am not trying to add a feature for prefix sites or anyone else. The driver is simple too aggressive without any benefit.
Comment #5
Crell CreditAttribution: Crell commentedWhat about Damien's comment in #2? Just overriding the method without thinking of the impact on other weird things we're doing to the table name is a hack.
Comment #6
moshe weitzman CreditAttribution: moshe weitzman commentedI did read #2 and discussed it with DamZ in IRC.
So, let me ask. Why does the mysql driver need to strip periods from table names? The only answer I am hearing is "We need to impede developers who don't use table prefixes from doing stuff that is impossible on sites that do use table prefixes." You can probably tell that I think this is going much too far.
Comment #7
Crell CreditAttribution: Crell commentedIf we're going to allow periods, shouldn't that at least be allowed for all drivers, not just the MySQL one? We want to make certain that we can get the behavior of all supported databases as close as possible.
Comment #8
moshe weitzman CreditAttribution: moshe weitzman commentedNow allowing period for all drivers.
Comment #9
Crell CreditAttribution: Crell commentedEr, wait. I just realized something I should have realized days ago.
The period needs to be OUTSIDE the table name. Prefixing happens on the table name, not the DB name. So if you're joining across databases, you should be doing this anyway:
Shouldn't you? Is there a detail here I'm missing?
Comment #10
moshe weitzman CreditAttribution: moshe weitzman commentedThe problem comes in dynamic queries where table names get escaped. I don't see how your comment is applicable there. Consider:
db_select('external.users)->execute();. That period gets stripped today.
Comment #11
Crell CreditAttribution: Crell commentedAh! Hm. Well, that's going to be a problem anyway if there's a prefix defined, because it will prefix the DB name, not the tablename, wouldn't it?
DBTNG was not designed for cross-DB joins in part because that's a MySQLism AFAIK, and very much an edge-case.
If we're going to allow periods in table names, then the patch in #8 looks correct with the caveat that it will still break with prefixing. I'm torn on whether or not that's a deal-breaking caveat.
I'd prefer to get input from the rest of the DB team here.
Comment #12
moshe weitzman CreditAttribution: moshe weitzman commentedI completely agree that DBTNG was not designed to support periods in table names. Even after this is committed, it won't be a supported feature. We don't need to actively prevent it either.
Comment #13
aaron CreditAttribution: aaron commentedConsidering: db_select('external.users)->execute(); I really don't see, considering {prefixing} how it would be fixed -- if you had, say a prefix of mydb_, that would be turned into "SELECT ... FROM mydb_external.users ..." I think that it would be better to somehow allow external db's; perhaps like db_select('users')->external('external')?
However, in that case, an external db might not want to have prefixes anyway. I think the whole thing is opening a big can of worms, and needs to be thought out in more detail. Committing this patch would achieve absolutely nothing, IMHO.
Comment #14
moshe weitzman CreditAttribution: moshe weitzman commented@aaron. your reply suggests that you think we are trying to add a feature here and that feature is poorly implemented. Thats not I intend.
Lets turn this around. Code should exist for a reason. Why does the code for stripping periods need to exist?
Comment #15
Crell CreditAttribution: Crell commentedWell just to confuse the issue, I checked through the CVS records. And I found no period. I just did a cvs up, and the escapeTable() in database.inc has no period. In fact I found no record of a period in the CVS logs anywhere.
Someone please explain to me why I am going rapidly insane, because I don't know how that's possible if #8 above is passing the bot.
Comment #16
Frando CreditAttribution: Frando commentedThe patch in #8 is adding the dot to the characters that are not stripped.
Comment #17
Crell CreditAttribution: Crell commentedOK, so I am just going crazy. That's what I get for trying to do 5 things at once this morning. *sigh*
In that case, the current whitelist has been the same going back to 4.7. Before that it doesn't seem to exist. I couldn't tell you why that was selected originally. For DBTNG I just carried that escaping logic forward as-is.
I suspect it was to avoid "whoops, wrong database!" problems, since a period is NOT a valid character in a table name.
Comment #18
moshe weitzman CreditAttribution: moshe weitzman commentedI have never seen any sanitizing of table names before DBTNG landed. We only used placeholders in WHERE. So this particular escaping does not go back to 4.7 AFAICT ... Now I feel like the one going crazy.
Comment #19
catchCrell is referring to db_escape_table() no?
http://api.drupal.org/api/function/db_escape_table
If so, that was only applied to four functions in D6, not to db_query() or update_sql().
Comment #20
Dries CreditAttribution: Dries commentedLooks like this might be a small design flaw in the API?
I'll leave it up to Crell to sign off on the final fix.
Comment #21
catchMaybe Crell will take another look if I mark this RTBC. We've confirmed that this is a new restriction in D7, given the old one didn't apply to select queries at all. I'm not sure what else there is to do here.
Comment #22
Crell CreditAttribution: Crell commentedSince I don't know what the original logic was for db_escape_table() in the first place, I'm OK with this unless someone from the security team sees a reason not to.
(Sorry, this patch fell off my radar for a bit.)
Comment #23
Dries CreditAttribution: Dries commentedCommitted to CVS HEAD. Thanks.