Skip to content
Permalink
Browse files

Making HasOne able to work with multi column primary keys

  • Loading branch information...
lorenzo committed Jan 9, 2014
1 parent 386394c commit cf9ee7ba22d9e3c7836f1bec58df48200bedf6e5
@@ -145,7 +145,7 @@ protected function _joinCondition(array $options) {
$tAlias = $this->target()->alias();
$sAlias = $this->_sourceTable->alias();
$foreignKey = (array)$options['foreignKey'];
$primaryKey = $this->_targetTable->primaryKey();
$primaryKey = (array)$this->_targetTable->primaryKey();
if (count($foreignKey) !== count($primaryKey)) {
$msg = 'Cannot match provided foreignKey, got %d columns expected %d';
@@ -40,7 +40,7 @@ public function cascadeDelete(Entity $entity, $options = []) {
}
$table = $this->target();
$foreignKey = (array)$this->foreignKey();
$primaryKey = $this->source()->primaryKey();
$primaryKey = (array)$this->source()->primaryKey();
$conditions = array_combine($foreignKey, $entity->extract($primaryKey));
if ($this->_cascadeCallbacks) {
@@ -134,16 +134,28 @@ public function save(Entity $entity, $options = []) {
*
* @param array $options list of options passed to attachTo method
* @return array
* @throws \RuntimeException if the number of columns in the foreignKey do not
* match the number of columns in the source table primaryKey
*/
protected function _joinCondition(array $options) {
$field = sprintf('%s.%s',
$this->_sourceTable->alias(),
$this->_sourceTable->primaryKey()
);
$value = new IdentifierExpression(sprintf(
'%s.%s', $this->_targetTable->alias(), $options['foreignKey']
));
return [$field => $value];
$conditions = [];
$tAlias = $this->target()->alias();
$sAlias = $this->_sourceTable->alias();
$foreignKey = (array)$options['foreignKey'];
$primaryKey = $this->_sourceTable->primaryKey();
if (count($foreignKey) !== count($primaryKey)) {
$msg = 'Cannot match provided foreignKey, got %d columns expected %d';
throw new \RuntimeException(sprintf($msg, count($foreignKey), count($primaryKey)));
}
foreach ($foreignKey as $k => $f) {
$field = sprintf('%s.%s', $sAlias, $primaryKey[$k]);
$value = new IdentifierExpression(sprintf('%s.%s', $tAlias, $f));
$conditions[$field] = $value;
}
return $conditions;
}
}
@@ -1042,7 +1042,7 @@ protected function _collectKeys($statement) {
if ($meta['instance']->requiresKeys($meta['config'])) {
$alias = $source->alias();
$pkFields = [];
foreach($source->primaryKey() as $key) {
foreach ((array)$source->primaryKey() as $key) {
$pkFields[] = key($this->aliasField($key, $alias));
}
$collectKeys[] = [$alias, $pkFields, count($pkFields) === 1];
@@ -829,7 +829,7 @@ public function findThreaded(Query $query, array $options = []) {
*/
public function get($primaryKey, $options = []) {
$key = (array)$this->primaryKey();
$conditions = array_combine($key, (array)$primaryKey);
$conditions = array_combine($key, $primaryKey);
$entity = $this->find('all', $options)->where($conditions)->first();
if (!$entity) {
@@ -212,6 +212,58 @@ public function testAttachToWithQueryBuilder() {
$association->attachTo($query, ['queryBuilder' => $builder]);
}
/**
* Tests that using hasOne with a table having a multi column primary
* key will work if the foreign key is passed
*
* @return void
*/
public function testAttachToMultiPrimaryKey() {
$query = $this->getMock('\Cake\ORM\Query', ['join', 'select'], [null, null]);
$config = [
'sourceTable' => $this->user,
'targetTable' => $this->profile,
'conditions' => ['Profiles.is_active' => true],
'foreignKey' => ['user_id', 'user_site_id']
];
$this->user->primaryKey(['id', 'site_id']);
$association = new HasOne('Profiles', $config);
$field1 = new IdentifierExpression('Profiles.user_id');
$field2 = new IdentifierExpression('Profiles.user_site_id');
$query->expects($this->once())->method('join')->with([
'Profiles' => [
'conditions' => new QueryExpression([
'Profiles.is_active' => true,
['Users.id' => $field1, 'Users.site_id' => $field2],
]),
'type' => 'INNER',
'table' => 'profiles'
]
]);
$query->expects($this->never())->method('select');
$association->attachTo($query, ['includeFields' => false]);
}
/**
* Tests that using hasOne with a table having a multi column primary
* key will work if the foreign key is passed
*
* @expectedException \RuntimeException
* @expectedExceptionMessage Cannot match provided foreignKey, got 1 columns expected 2
* @return void
*/
public function testAttachToMultiPrimaryKeyMistmatch() {
$query = $this->getMock('\Cake\ORM\Query', ['join', 'select'], [null, null]);
$config = [
'sourceTable' => $this->user,
'targetTable' => $this->profile,
'conditions' => ['Profiles.is_active' => true],
];
$this->user->primaryKey(['id', 'site_id']);
$association = new HasOne('Profiles', $config);
$association->attachTo($query, ['includeFields' => false]);
}
/**
* Test that save() ignores non entity values.
*

0 comments on commit cf9ee7b

Please sign in to comment.
You can’t perform that action at this time.