Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Fix `data\source\Database::read()` hack. #752

Merged
merged 2 commits into from

2 participants

@jails
Collaborator

With this PR array('return' => 'array') option on queries with relations will return something like the following:

array(
    'field1' => 'value1',
    'field2' => 'value2',
    'field3' => 'value3',
    /* ... other fields ... */
    'relation_fieldname' => array(
             'field1' => 'value1',
             'field2' => 'value2',
             'field3' => 'value3',
             /* ... other fields ... */
             'subrelation_fieldname' => array(
                   /*...*/
             )
 );
@nateabele nateabele merged commit 832578a into UnionOfRAD:dev

1 check passed

Details default The Travis build passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
34 data/model/Query.php
@@ -98,7 +98,7 @@ class Query extends \lithium\core\Object {
protected $_alias = array();
/**
- * Map the generated aliases to their corresponding relation path
+ * Map beetween generated aliases and corresponding relation paths
*
* @see lithium\data\model\Query::alias()
*
@@ -107,7 +107,16 @@ class Query extends \lithium\core\Object {
protected $_paths = array();
/**
- * Map the generated aliases to their corresponding model
+ * Map beetween relation paths and their corresponding fieldname paths
+ *
+ * @see lithium\data\model\Query::alias()
+ *
+ * @var array
+ */
+ protected $_relationNames = array();
+
+ /**
+ * Map beetween generated aliases and corresponding models.
*
* @see lithium\data\model\Query::alias()
*
@@ -720,23 +729,40 @@ public function alias($alias = true, $relpath = null) {
}
$this->_paths[$alias] = $relpath;
+ $fieldname = array();
foreach ($paths as $path) {
if (!$relation = $model::relations($path)) {
$model = null;
break;
}
+ $fieldname[] = $relation->fieldName();
$model = $relation->to();
}
$this->_models[$alias] = $model;
+ $this->_relationNames[$relpath] = join('.', $fieldname);
return $alias;
}
/**
+ * Return the relation paths mapped to their corredponding fieldname paths.
+ *
+ * @param object $source Instance of the data source (`lithium\data\Source`) to use for
+ * conversion.
+ * @return array Map between relation paths and their corresponding fieldname paths.
+ */
+ public function relationNames(Source $source = null) {
+ if ($source) {
+ $this->applyStrategy($source);
+ }
+ return $this->_relationNames;
+ }
+
+ /**
* Return the generated aliases mapped to their relation path
*
* @param object $source Instance of the data source (`lithium\data\Source`) to use for
* conversion.
- * @return array Map between alias and their corresponding dotted relation
+ * @return array Map between aliases and their corresponding dotted relation paths.
*/
public function paths(Source $source = null) {
if ($source) {
@@ -750,7 +776,7 @@ public function paths(Source $source = null) {
*
* @param object $source Instance of the data source (`lithium\data\Source`) to use for
* conversion.
- * @return array Map between alias and their corresponding model
+ * @return array Map between aliases and their corresponding fully-namespaced model names.
*/
public function models(Source $source = null) {
if ($source) {
View
30 data/source/Database.php
@@ -465,18 +465,30 @@ public function read($query, array $options = array()) {
return $result;
case 'array':
$columns = $args['schema'] ?: $self->schema($query, $result);
- $records = array();
- if (is_array(reset($columns))) {
- $columns = reset($columns);
+
+ if (!isset($columns['']) || !is_array($columns[''])) {
+ $columns = array('' => $columns);
}
- while ($data = $result->next()) {
- // @hack: Fix this to support relationships
- if (count($columns) != count($data) && is_array(current($columns))) {
- $columns = current($columns);
+
+ $relationNames = is_object($query) ? $query->relationNames($self) : array();
+ $i = 0;
+ $records = array();
+ foreach ($result as $data) {
+ $offset = 0;
+ $records[$i] = array();
+ foreach ($columns as $path => $cols) {
+ $len = count($cols);
+ $values = array_combine($cols, array_slice($data, $offset, $len));
+ if ($path) {
+ $records[$i][$relationNames[$path]] = $values;
+ } else {
+ $records[$i] += $values;
+ }
+ $offset += $len;
}
- $records[] = array_combine($columns, $data);
+ $i++;
}
- return $records;
+ return Set::expand($records);
case 'item':
return $self->item($query->model(), array(), compact('query', 'result') + array(
'class' => 'set'
View
21 tests/cases/data/model/QueryTest.php
@@ -633,6 +633,27 @@ public function testModels() {
$this->assertEqual($expected, $query->models($this->db));
}
+ public function testRelationNames() {
+ $model = 'lithium\tests\mocks\data\model\MockQueryPost';
+ $query = new Query(compact('model'));
+ $query->alias(null, 'MockQueryComment');
+
+ $expected = array(
+ 'MockQueryComment' => 'mock_query_comments'
+ );
+ $this->assertEqual($expected, $query->relationNames($this->db));
+
+ $query->alias('Post');
+ $query->alias('Comment', 'MockQueryComment');
+ $query->alias('Post2', 'MockQueryComment.MockQueryPost');
+
+ $expected = array(
+ 'MockQueryComment' => 'mock_query_comments',
+ 'MockQueryComment.MockQueryPost' => 'mock_query_comments.mock_query_post'
+ );
+ $this->assertEqual($expected, $query->relationNames($this->db));
+ }
+
public function testExportWithJoinedStrategy() {
$query = new Query(array(
'alias' => 'MyAlias',
View
80 tests/cases/data/source/DatabaseTest.php
@@ -16,6 +16,7 @@
use lithium\tests\mocks\data\model\MockDatabaseComment;
use lithium\tests\mocks\data\model\MockDatabaseTagging;
use lithium\tests\mocks\data\model\MockDatabasePostRevision;
+use lithium\tests\mocks\data\model\mock_database\MockResult;
class DatabaseTest extends \lithium\test\Unit {
@@ -42,6 +43,7 @@ public function setUp() {
public function tearDown() {
$this->db->logs = array();
+ $this->db->return = array();
}
public function testDefaultConfig() {
@@ -1498,6 +1500,84 @@ public function testCustomField() {
$this->assertEqual($expected, $this->db->sql);
$this->assertEqual($map, $query->map());
}
+
+ public function testReturnArrayOnReadWithString() {
+ $data = new MockResult(array('records' => array(
+ array ('id', 'int(11)', 'NO', 'PRI', null, 'auto_increment'),
+ array ('name', 'varchar(256)', 'YES', '', null, '')
+ )));
+ $this->db->return = array(
+ 'schema' => array('field', 'type', 'null', 'key', 'default', 'extra'),
+ '_execute' => $data
+ );
+ $result = $this->db->read('DESCRIBE {table};', array('return' => 'array'));
+ $expected = array(
+ array(
+ 'field' => 'id',
+ 'type' => 'int(11)',
+ 'null' => 'NO',
+ 'key' => 'PRI',
+ 'default' => null,
+ 'extra' => 'auto_increment',
+ ),
+ array(
+ 'field' => 'name',
+ 'type' => 'varchar(256)',
+ 'null' => 'YES',
+ 'key' => '',
+ 'default' => null,
+ 'extra' => '',
+ )
+ );
+ $this->assertEqual($expected, $result);
+ }
+
+ public function testReturnArrayOnReadWithQuery() {
+ $data = new MockResult(array('records' => array(array(
+ '1',
+ '2',
+ 'Post title',
+ '2012-12-17 17:04:00',
+ '3',
+ '1',
+ '2',
+ 'Very good post',
+ '2012-12-17 17:05:00',
+ '1',
+ '2',
+ 'Post title',
+ '2012-12-17 17:04:00',
+ ))));
+ $this->db->return = array(
+ '_execute' => $data
+ );
+ $query = new Query(array(
+ 'type' => 'read',
+ 'model' => $this->_model,
+ 'with' => array('MockDatabaseComment.MockDatabasePost')
+ ));
+ $result = $this->db->read($query, array('return' => 'array'));
+ $expected = array(array(
+ 'id' => '1',
+ 'author_id' => '2',
+ 'title' => 'Post title',
+ 'created' => '2012-12-17 17:04:00',
+ 'mock_database_comments' => array(
+ 'id' => '3',
+ 'post_id' => '1',
+ 'author_id' => '2',
+ 'body' => 'Very good post',
+ 'created' => '2012-12-17 17:05:00',
+ 'mock_database_post' => array(
+ 'id' => '1',
+ 'author_id' => '2',
+ 'title' => 'Post title',
+ 'created' => '2012-12-17 17:04:00',
+ )
+ )
+ ));
+ $this->assertEqual($expected, $result);
+ }
}
?>
View
12 tests/mocks/data/model/MockDatabase.php
@@ -41,6 +41,8 @@ class MockDatabase extends \lithium\data\source\Database {
public $log = false;
+ public $return = array();
+
protected $_quotes = array('{', '}');
public function __construct(array $config = array()) {
@@ -94,9 +96,19 @@ protected function _execute($sql) {
if ($this->log) {
$this->logs[] = $sql;
}
+ if (isset($this->return['_execute'])) {
+ return $this->return['_execute'];
+ }
return new MockResult();
}
+ public function schema($query, $resource = null, $context = null) {
+ if (isset($this->return['schema'])) {
+ return $this->return['schema'];
+ }
+ return parent::schema($query, $resource = null, $context = null);
+ }
+
protected function _insertId($query) {
$query = $query->export($this);
ksort($query);
Something went wrong with that request. Please try again.