Skip to content

Commit

Permalink
First implementation of database queries
Browse files Browse the repository at this point in the history
  • Loading branch information
mtils committed Mar 28, 2020
1 parent d2c7b7b commit 80cbe00
Show file tree
Hide file tree
Showing 3 changed files with 348 additions and 1 deletion.
72 changes: 72 additions & 0 deletions src/Ems/Core/Support/GenericRenderer.php
@@ -0,0 +1,72 @@
<?php

/**
* * Created by mtils on 28.03.20 at 07:51.
**/

namespace Ems\Core\Support;

use Ems\Contracts\Core\Renderable;
use Ems\Contracts\Core\Renderer;
use Ems\Contracts\Core\Stringable;

use function call_user_func;

/**
* Class GenericRenderer
*
* This is a helper to create a renderer on the fly.
*
* @package Ems\Core\Support
*/
class GenericRenderer implements Renderer
{
/**
* @var callable
*/
private $canRenderCallable;

/**
* @var callable
*/
private $renderCallable;

/**
* GenericRenderer constructor.
*
* @param callable $renderCallable
* @param callable $canRenderCallable (optional)
*/
public function __construct(callable $renderCallable, callable $canRenderCallable = null)
{
$this->renderCallable = $renderCallable;
$this->canRenderCallable = $canRenderCallable ?: function () {
return true;
};
}

/**
* {@inheritDoc}
*
* @param Renderable
*
* @return bool
**/
public function canRender(Renderable $item)
{
return call_user_func($this->canRenderCallable, $item);
}

/**
* {@inheritDoc}
*
* @param Renderable $item
*
* @return string|Stringable
**/
public function render(Renderable $item)
{
return call_user_func($this->renderCallable, $item);
}

}
2 changes: 1 addition & 1 deletion src/Ems/Model/Database/Query.php
Expand Up @@ -214,7 +214,7 @@ public function createPaginatorBy(callable $factory)
protected function getTotalCount()
{
$result = $this->readFromConnection($this->getTotalCountQuery())->first();
return $result ? $result['total'] : 0;
return $result ? (int)$result['total'] : 0;
}

/**
Expand Down
275 changes: 275 additions & 0 deletions tests/integration/Model/Database/QueryIntegrationTest.php
Expand Up @@ -10,7 +10,9 @@
use DateTimeInterface;
use Ems\Contracts\Model\Database\Connection;
use Ems\Contracts\Model\Database\Dialect;
use Ems\Core\Expression;
use Ems\Core\Filesystem\CsvReadIterator;
use Ems\Core\Support\GenericRenderer;
use Ems\Core\Url;
use Ems\IntegrationTest;
use Ems\Model\Database\Dialects\SQLiteDialect;
Expand Down Expand Up @@ -132,6 +134,33 @@ public function select_paginated()

}

/**
* @test
*/
public function select_paginated_with_custom_count_query()
{

$perPage = 10;
$query = static::$con->query('users');

$countQuery = clone $query;
$countQuery->offset(null)->limit(null);
$countQuery->columns = [];
$countQuery->orderBys = [];
$countQuery->select(new Expression('250 as total'));

$this->assertSame($query, $query->setCountQuery($countQuery));
$this->assertSame($countQuery, $query->getCountQuery());


$query->join('contacts')->on('users.contact_id', 'contacts.id');

$items = $query->orderBy('id')->paginate(1, $perPage);
$this->assertInstanceOf(Paginator::class, $items);
$this->assertSame(250, $items->getTotalCount());

}

/**
* @test
*/
Expand Down Expand Up @@ -224,6 +253,252 @@ public function select_paginated_with_custom_paginator()

}

/**
* @test
*/
public function replace_inserts_or_updates()
{
$query = static::$con->query('contacts');

$firstName = 'Reed';
$lastName = 'Weisinger';

$newLastName = 'Weisinger2';
$newFirstName = 'Reed2';

$users = $query->where('last_name', $lastName)
->where('first_name', $firstName);

$found = iterator_to_array($users);
$this->assertCount(1, $found);
$this->assertEquals($lastName, $found[0]['last_name']);

$affected = static::$con->query('contacts')->replace([
'id' => $found[0]['id'],
'last_name' => $newLastName,
'first_name' => $newFirstName,
'created_at' => new DateTime(),
'updated_at' => new DateTime(),
]);

$this->assertSame(1, $affected);

$users = static::$con->query('contacts')->where('last_name', $lastName)
->where('first_name', $firstName);

$found = iterator_to_array($users);
$this->assertCount(0, $found);

$maxId = static::$con->query('contacts')
->select(new Expression('MAX(id) AS max_id'))
->first()['max_id'];

$this->assertEquals(500, $maxId);

$nextId = (int)$maxId+1;

$affected = static::$con->query('contacts')->replace([
'id' => $nextId,
'last_name' => $lastName,
'first_name' => $firstName,
'created_at' => new DateTime(),
'updated_at' => new DateTime(),
]);

$this->assertSame(1, $affected);

$users = static::$con->query('contacts')
->where('last_name', $lastName)
->where('first_name', $firstName);

$found = iterator_to_array($users);
$this->assertCount(1, $found);

}

/**
* @test
*/
public function update_changes_record()
{
$user = static::$con->query('contacts')
->where('last_name', 'Ear')
->where('first_name', 'Luis')
->first();

$this->assertEquals('Luis', $user['first_name']);
$this->assertEquals('Ear', $user['last_name']);
$this->assertEquals('Whittington', $user['city']);
$this->assertEquals('Shropshire', $user['county']);

$affected = static::$con->query('contacts')
->where('id', $user['id'])
->update([
'city' => 'Köln',
'county' => 'Nordrhein Westfalen'
]);

$this->assertSame(1, $affected);

$user = static::$con->query('contacts')
->where('last_name', 'Ear')
->where('first_name', 'Luis')
->first();

$this->assertEquals('Luis', $user['first_name']);
$this->assertEquals('Ear', $user['last_name']);
$this->assertEquals('Köln', $user['city']);
$this->assertEquals('Nordrhein Westfalen', $user['county']);

}

/**
* @test
*/
public function delete_removes_record()
{
$lastName = 'Weisinger2';
$firstName = 'Reed2';


$user = static::$con->query('contacts')
->where('last_name', $lastName)
->where('first_name', $firstName)
->first();

$this->assertEquals($lastName, $user['last_name']);

$affected = static::$con->query('contacts')
->where('last_name', $lastName)
->where('first_name', $firstName)
->delete();

$this->assertSame(1, $affected);

$this->assertNull(static::$con->query('contacts')
->where('last_name', $lastName)
->where('first_name', $firstName)
->first());
}

/**
* @test
*/
public function insert_creates_record()
{
$query = static::$con->query('contacts');

$firstName = 'Michael';
$lastName = 'Tils';

$users = $query->where('last_name', $lastName)
->where('first_name', $firstName);

$found = iterator_to_array($users);
$this->assertCount(0, $found);

$insertedId = static::$con->query('contacts')->insert(
[
'last_name' => $lastName,
'first_name' => $firstName,
'created_at' => new DateTime(),
'updated_at' => new DateTime(),
]
);

$this->assertGreaterThan(500, $insertedId);


$users = static::$con->query('contacts')
->where('last_name', $lastName)
->where('first_name', $firstName);

$found = iterator_to_array($users);
$this->assertCount(1, $found);

$this->assertEquals($firstName, $found[0]['first_name']);
$this->assertEquals($lastName, $found[0]['last_name']);
}

/**
* @test
*/
public function select_with_unprepared_query()
{
$query = static::$con->query('contacts');
$renderer = $query->getRenderer();

$proxy = new GenericRenderer(function ($query) use ($renderer) {
$expression = $renderer->render($query);
return SQL::render($expression->toString(), $expression->getBindings());
});

$query->setRenderer($proxy);

$query->where('last_name', 'like', 'C%');

$count = 0;
foreach ($query as $row) {
if ($row['last_name'][0] != 'C') {
$this->fail('Not matching last name found');
}
$count++;
}

$this->assertGreaterThan(1, $count);
}

/**
* @test
*/
public function insert_with_unprepared_query()
{
$query = static::$con->query('contacts');

$firstName = 'Michaela';
$lastName = 'Tils';

$users = $query->where('last_name', $lastName)
->where('first_name', $firstName);

$found = iterator_to_array($users);
$this->assertCount(0, $found);

$insertQuery = static::$con->query('contacts');
$renderer = $query->getRenderer();

$proxy = new GenericRenderer(function ($query) use ($renderer) {
$expression = $renderer->render($query);
return SQL::render($expression->toString(), $expression->getBindings());
});

$this->assertTrue($proxy->canRender($insertQuery));

$insertQuery->setRenderer($proxy);

$insertedId = $insertQuery->insert(
[
'last_name' => $lastName,
'first_name' => $firstName,
'created_at' => new DateTime(),
'updated_at' => new DateTime(),
]
);

$this->assertGreaterThan(500, $insertedId);


$users = static::$con->query('contacts')
->where('last_name', $lastName)
->where('first_name', $firstName);

$found = iterator_to_array($users);
$this->assertCount(1, $found);

$this->assertEquals($firstName, $found[0]['first_name']);
$this->assertEquals($lastName, $found[0]['last_name']);
}

/**
* @beforeClass
*/
Expand Down

0 comments on commit 80cbe00

Please sign in to comment.