Patch #2634
Kohana_ORM::with() does not work well when Database uses prefixes
| Status: | Closed | Start date: | 02/20/2010 | |
|---|---|---|---|---|
| Priority: | Normal | Due date: | ||
| Assignee: | % Done: | 0% |
||
| Category: | Modules:ORM | |||
| Target version: | v3.0.4 | |||
| Resolution: | fixed | Points: |
Description
Say, we have two tables: users and subscriptions:
CREATE TABLE prefix_users (
id INTEGER NOT NULL PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
CREATE TABLE prefix_subscriptions (
id INTEGER NOT NULL PRIMARY KEY,
user_id INTEGER UNSIGNED NOT NULL,
some_data TEXT NOT NULL
);
A user has_many subscriptions, a subscription belongs_to one user.
We have two models describing the tables above:
class Model_User extends ORM {
protected $_has_many = array(
'subscriptions' => array(
'foreign_key' => 'user_id',
'model' => 'Subscription',
),
);
}
class Model_Subscription extends ORM {
protected $_belongs_to = array(
'user' => array(
'foreign_key' => 'user_id',
'model' => 'User',
),
);
}
Database connection configuration is as follows:
return array(
'default' => array(
'type' => 'mysql',
'connection' => array( /* Omitted for the sake of brevity */),
'table_prefix' => 'prefix_', // <<< This is the crucial part
),
);
Now, if we call something like ORM::factory('Subscription')->with('user')->find_all(); we will get an exception (I have reformatted the message for the sake of readability):
Database_Exception [ 1054 ]: Unknown column 'prefix_user.id' in 'field list' [ SELECT `prefix_user`.`id` AS `user:id`, `prefix_user`.`name` AS `user:name`, `prefix_subscriptions`.* FROM `prefix_subscriptions` LEFT JOIN `prefix_users` AS `user` ON (`prefix_user`.`id` = `prefix_subscriptions`.`user_id`) ORDER BY `prefix_subscriptions`.`id` ASC ] ~ MODPATH/database/classes/kohana/database/mysql.php [ 183 ]
The problem is that the Database module is unaware of table aliases (thus replacing all user. with prefix_user.) and ORM module is unaware of table prefixes.
The patch that fixes the issue is attached.
Related issues
History
Updated by John Heathco almost 2 years ago
- Target version changed from v3.0.3 to v3.0.4
Updated by Woody Gilk almost 2 years ago
- Status changed from New to Assigned
- Assignee set to John Heathco
Updated by John Heathco almost 2 years ago
Is this an issue with the DB or ORM? It looks like your patch involves quoting the columns - something that should be done in the DB layer...
Updated by Vladimir Kolesnikov almost 2 years ago
I am not sure this is possible at the DB layer. Quoting is necessary to stop the DB layer from adding the prefixes to table aliases.
Database layer is not aware of table aliases, ORM is not aware of table prefixes.
You get something like
DB::instance()
->select(/* skipped */)
->join(array('users', 'user'), 'LEFT')
->on('user.id', '=', 'subscriptions.user_id')
->order_by('subscriptions.id', 'ASC)
Database layer does not know if "user" in the ON clause is a table (should be prefixed) or alias (should not be prefixed).
Updated by Vladimir Kolesnikov almost 2 years ago
Quoting the tables is the only way (at least that I am aware of) to force the DB layer not to add prefixes. But if we pass something like "alias".column to the DB layer, it won't quote column part (will have `alias`.column) which can break the query if a column name matches the reserved word.
Updated by Woody Gilk almost 2 years ago
- Target version changed from v3.0.4 to v3.0.5
Updated by John Heathco almost 2 years ago
The best solution is simply to attach the prefix to the join statement in ORM..
Updated by John Heathco almost 2 years ago
- Status changed from Assigned to Closed
- Target version changed from v3.0.5 to 175
- Resolution set to fixed
Updated by Woody Gilk almost 2 years ago
- Target version changed from 175 to v3.0.4