Skip to content

Commit

Permalink
fix bugs. add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
taylorotwell committed May 24, 2016
1 parent 618c9ed commit d48e531
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 28 deletions.
17 changes: 10 additions & 7 deletions src/Illuminate/Database/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -343,12 +343,12 @@ public function select($query, $bindings = [], $useReadPdo = true)
}

/**
* Run a select statement against the database and returns a cursor.
* Run a select statement against the database and returns a generator.
*
* @param string $query
* @param array $bindings
* @param bool $useReadPdo
* @return mixed
* @return \Generator
*/
public function cursor($query, $bindings = [], $useReadPdo = true)
{
Expand All @@ -357,16 +357,19 @@ public function cursor($query, $bindings = [], $useReadPdo = true)
return [];
}

// For select statements, we'll simply execute the query and return an array
// of the database result set. Each element in the array will be a single
// row from the database table, and will either be an array or objects.
$statement = $this->getPdoForSelect($useReadPdo)->prepare($query);

$statement->setFetchMode($me->getFetchMode());
if ($me->getFetchMode() === PDO::FETCH_CLASS) {
$statement->setFetchMode($me->getFetchMode(), 'StdClass');
} else {
$statement->setFetchMode($me->getFetchMode());
}

This comment has been minimized.

Copy link
@vlakoff

vlakoff Jun 17, 2016

Contributor

What if the user specified PDO::FETCH_CLASS and a class name ($fetchArgument)?

Maybe the code in select() method above could be of inspiration.

This comment has been minimized.

Copy link
@vlakoff

vlakoff Jun 18, 2016

Contributor

Also as it may be of interest, refs #12171.

This comment has been minimized.

Copy link
@vlakoff

vlakoff Jun 18, 2016

Contributor

See also laravel/laravel#3814. Note we use setFetchMode() here, whereas select() uses fetchAll().

$statement->execute($me->prepareBindings($bindings));

return $statement;
while ($record = $statement->fetch()) {
yield $record;
}
});
}

Expand Down
21 changes: 4 additions & 17 deletions src/Illuminate/Database/Eloquent/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -304,29 +304,16 @@ public function firstOrFail($columns = ['*'])
}

/**
* Traverses through a result set using a cursor.
* Get a generator for the given query.
*
* @return void
* @return \Generator
*/
public function cursor()
{
$builder = $this->applyScopes();

$statement = $builder->query->cursor();

while ($row = $statement->fetch()) {
// On each result set, we will pass them to the callback and then let the
// developer take care of everything within the callback, which allows us to
// keep the memory low for spinning through large result sets for working.

if ($row === false) {
return;
}

//Hydrate and yield an Eloquent Model
$model = $this->model->newFromBuilder($row);

yield $model;
foreach ($builder->query->cursor() as $record) {
yield $this->model->newFromBuilder($record);
}
}

Expand Down
12 changes: 8 additions & 4 deletions src/Illuminate/Database/Query/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -1693,15 +1693,19 @@ protected function restoreFieldsForCount()
}

/**
* Execute the query as a "select" statement.
* Get a generator for the given query.
*
* @return mixed
* @return \Generator
*/
public function cursor()
{
$results = $this->connection->cursor($this->toSql(), $this->getBindings(), ! $this->useWritePdo);
if (is_null($this->columns)) {
$this->columns = ['*'];
}

return $results;
return $this->connection->cursor(
$this->toSql(), $this->getBindings(), ! $this->useWritePdo
);
}

/**
Expand Down
15 changes: 15 additions & 0 deletions tests/Database/DatabaseEloquentIntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,21 @@ public function testBasicModelRetrieval()
$collection = EloquentTestUser::find([1, 2, 3]);
$this->assertInstanceOf('Illuminate\Database\Eloquent\Collection', $collection);
$this->assertEquals(2, $collection->count());

$models = EloquentTestUser::where('id', 1)->cursor();
foreach ($models as $model) {
$this->assertEquals(1, $model->id);
}

$records = DB::table('users')->where('id', 1)->cursor();
foreach ($records as $record) {
$this->assertEquals(1, $record->id);
}

$records = DB::cursor('select * from users where id = ?', [1]);
foreach ($records as $record) {
$this->assertEquals(1, $record->id);
}
}

public function testBasicModelCollectionRetrieval()
Expand Down

0 comments on commit d48e531

Please sign in to comment.