Abandoned FPDO

Also, fixed tag search by categories
This commit is contained in:
Marcin Kurczewski 2014-10-19 19:52:27 +02:00
parent c55c0833ea
commit c52ed6a455
23 changed files with 740 additions and 61 deletions

View file

@ -1,7 +1,6 @@
{
"require": {
"mnapoli/php-di": "~4.0",
"lichtner/fluentpdo": "dev-master"
"mnapoli/php-di": "~4.0"
},
"require-dev": {

View file

@ -13,7 +13,6 @@ use Szurubooru\SearchServices\Result;
abstract class AbstractDao implements ICrudDao, IBatchDao
{
protected $pdo;
protected $fpdo;
protected $tableName;
protected $entityConverter;
protected $driver;
@ -64,7 +63,7 @@ abstract class AbstractDao implements ICrudDao, IBatchDao
public function findAll()
{
$query = $this->fpdo->from($this->tableName)->disableSmartJoin();
$query = $this->pdo->from($this->tableName);
$arrayEntities = iterator_to_array($query);
return $this->arrayToEntities($arrayEntities);
}
@ -81,7 +80,7 @@ abstract class AbstractDao implements ICrudDao, IBatchDao
public function findFiltered(IFilter $searchFilter)
{
$query = $this->fpdo->from($this->tableName)->disableSmartJoin();
$query = $this->pdo->from($this->tableName);
$orderByString = self::compileOrderBy($searchFilter->getOrder());
if ($orderByString)
@ -95,7 +94,7 @@ abstract class AbstractDao implements ICrudDao, IBatchDao
}
$entities = $this->arrayToEntities(iterator_to_array($query));
$query = $this->fpdo->from($this->tableName)->disableSmartJoin();
$query = $this->pdo->from($this->tableName);
$this->decorateQueryFromFilter($query, $searchFilter);
$totalRecords = count($query);
@ -114,7 +113,7 @@ abstract class AbstractDao implements ICrudDao, IBatchDao
{
$this->beforeDelete($entity);
}
$this->fpdo->deleteFrom($this->tableName)->execute();
$this->pdo->deleteFrom($this->tableName)->execute();
}
public function deleteById($entityId)
@ -125,14 +124,15 @@ abstract class AbstractDao implements ICrudDao, IBatchDao
public function update(Entity $entity)
{
$arrayEntity = $this->entityConverter->toArray($entity);
$this->fpdo->update($this->tableName)->set($arrayEntity)->where($this->getIdColumn(), $entity->getId())->execute();
unset($arrayEntity['id']);
$this->pdo->update($this->tableName)->set($arrayEntity)->where($this->getIdColumn(), $entity->getId())->execute();
return $entity;
}
public function create(Entity $entity)
{
$arrayEntity = $this->entityConverter->toArray($entity);
$this->fpdo->insertInto($this->tableName)->values($arrayEntity)->execute();
$this->pdo->insertInto($this->tableName)->values($arrayEntity)->execute();
$entity->setId(intval($this->pdo->lastInsertId()));
return $entity;
}
@ -144,14 +144,14 @@ abstract class AbstractDao implements ICrudDao, IBatchDao
protected function hasAnyRecords()
{
return count(iterator_to_array($this->fpdo->from($this->tableName)->limit(1))) > 0;
return count(iterator_to_array($this->pdo->from($this->tableName)->limit(1))) > 0;
}
protected function findBy($columnName, $value)
{
if (is_array($value) and empty($value))
return [];
$query = $this->fpdo->from($this->tableName)->disableSmartJoin()->where($columnName, $value);
$query = $this->pdo->from($this->tableName)->where($columnName, $value);
$arrayEntities = iterator_to_array($query);
return $this->arrayToEntities($arrayEntities);
}
@ -170,7 +170,7 @@ abstract class AbstractDao implements ICrudDao, IBatchDao
{
$this->beforeDelete($entity);
}
$this->fpdo->deleteFrom($this->tableName)->disableSmartJoin()->where($columnName, $value)->execute();
$this->pdo->deleteFrom($this->tableName)->where($columnName, $value)->execute();
}
protected function afterLoad(Entity $entity)
@ -197,7 +197,7 @@ abstract class AbstractDao implements ICrudDao, IBatchDao
if ($value instanceof RequirementCompositeValue)
{
$sql = $sqlColumn;
$bindings = [$value->getValues()];
$bindings = $value->getValues();
if ($requirement->isNegated())
$sql = 'NOT ' . $sql;
@ -239,7 +239,7 @@ abstract class AbstractDao implements ICrudDao, IBatchDao
else
throw new \Exception('Bad value: ' . get_class($value));
$query->where($sql, ...$bindings);
$query->where($sql, $bindings);
}
protected function arrayToEntities(array $arrayEntities, $entityConverter = null)
@ -259,7 +259,6 @@ abstract class AbstractDao implements ICrudDao, IBatchDao
private function setDatabaseConnection(DatabaseConnection $databaseConnection)
{
$this->pdo = $databaseConnection->getPDO();
$this->fpdo = new \FluentPDO($this->pdo);
$this->driver = $databaseConnection->getDriver();
}

View file

@ -60,7 +60,7 @@ class FavoritesDao extends AbstractDao implements ICrudDao
private function get(User $user, Entity $entity)
{
$query = $this->fpdo->from($this->tableName)->where('userId', $user->getId());
$query = $this->pdo->from($this->tableName)->where('userId', $user->getId());
if ($entity instanceof Post)
$query->where('postId', $entity->getId());

View file

@ -38,12 +38,12 @@ class PostDao extends AbstractDao implements ICrudDao
public function getCount()
{
return count($this->fpdo->from($this->tableName));
return count($this->pdo->from($this->tableName));
}
public function getTotalFileSize()
{
$query = $this->fpdo->from($this->tableName)->select('SUM(originalFileSize) AS __sum');
$query = $this->pdo->from($this->tableName)->select('SUM(originalFileSize) AS __sum');
return intval(iterator_to_array($query)[0]['__sum']);
}
@ -54,10 +54,9 @@ class PostDao extends AbstractDao implements ICrudDao
public function findByTagName($tagName)
{
$query = $this->fpdo->from('posts')
->disableSmartJoin()
->innerJoin('postTags ON postTags.postId = posts.id')
->innerJoin('tags ON postTags.tagId = tags.id')
$query = $this->pdo->from('posts')
->innerJoin('postTags', 'postTags.postId = posts.id')
->innerJoin('tags', 'postTags.tagId = tags.id')
->where('tags.name', $tagName);
$arrayEntities = iterator_to_array($query);
return $this->arrayToEntities($arrayEntities);
@ -184,21 +183,20 @@ class PostDao extends AbstractDao implements ICrudDao
private function getRelatedPosts(Post $post)
{
$query = $this->fpdo
->from('postRelations')
->where('post1id = :post1id OR post2id = :post2id', [
':post1id' => $post->getId(),
':post2id' => $post->getId()]);
$relatedPostIds = [];
foreach ($query as $arrayEntity)
foreach ($this->pdo->from('postRelations')->where('post1id', $post->getId()) as $arrayEntity)
{
$post1id = intval($arrayEntity['post1id']);
$post2id = intval($arrayEntity['post2id']);
if ($post1id !== $post->getId())
$relatedPostIds[] = $post1id;
if ($post2id !== $post->getId())
$relatedPostIds[] = $post2id;
$postId = intval($arrayEntity['post2id']);
if ($postId !== $post->getId())
$relatedPostIds[] = $postId;
}
foreach ($this->pdo->from('postRelations')->where('post2id', $post->getId()) as $arrayEntity)
{
$postId = intval($arrayEntity['post1id']);
if ($postId !== $post->getId())
$relatedPostIds[] = $postId;
}
return $this->findByIds($relatedPostIds);
@ -242,25 +240,25 @@ class PostDao extends AbstractDao implements ICrudDao
{
return $arrayEntity['tagId'];
},
iterator_to_array($this->fpdo->from('postTags')->where('postId', $post->getId())));
iterator_to_array($this->pdo->from('postTags')->where('postId', $post->getId())));
$tagRelationsToInsert = array_diff($tagIds, $existingTagRelationIds);
$tagRelationsToDelete = array_diff($existingTagRelationIds, $tagIds);
foreach ($tagRelationsToInsert as $tagId)
{
$this->fpdo->insertInto('postTags')->values(['postId' => $post->getId(), 'tagId' => $tagId])->execute();
$this->pdo->insertInto('postTags')->values(['postId' => $post->getId(), 'tagId' => $tagId])->execute();
}
foreach ($tagRelationsToDelete as $tagId)
{
$this->fpdo->deleteFrom('postTags')->where('postId', $post->getId())->where('tagId', $tagId)->execute();
$this->pdo->deleteFrom('postTags')->where('postId', $post->getId())->where('tagId', $tagId)->execute();
}
}
private function syncPostRelations(Post $post)
{
$this->fpdo->deleteFrom('postRelations')->where('post1id', $post->getId())->execute();
$this->fpdo->deleteFrom('postRelations')->where('post2id', $post->getId())->execute();
$this->pdo->deleteFrom('postRelations')->where('post1id', $post->getId())->execute();
$this->pdo->deleteFrom('postRelations')->where('post2id', $post->getId())->execute();
$relatedPostIds = array_filter(array_unique(array_map(
function ($post)
@ -273,7 +271,7 @@ class PostDao extends AbstractDao implements ICrudDao
foreach ($relatedPostIds as $postId)
{
$this->fpdo
$this->pdo
->insertInto('postRelations')
->values([
'post1id' => $post->getId(),

View file

@ -27,7 +27,7 @@ class ScoreDao extends AbstractDao implements ICrudDao
public function getScore(User $user, Entity $entity)
{
$query = $this->fpdo->from($this->tableName)->where('userId', $user->getId());
$query = $this->pdo->from($this->tableName)->where('userId', $user->getId());
if ($entity instanceof Post)
$query->where('postId', $entity->getId());

View file

@ -24,7 +24,7 @@ class SnapshotDao extends AbstractDao
public function findByTypeAndKey($type, $primaryKey)
{
$query = $this->fpdo
$query = $this->pdo
->from($this->tableName)
->where('type', $type)
->where('primaryKey', $primaryKey)

View file

@ -38,9 +38,8 @@ class TagDao extends AbstractDao implements ICrudDao
public function findByPostIds($postIds)
{
$query = $this->fpdo->from($this->tableName)
->disableSmartJoin()
->innerJoin('postTags ON postTags.tagId = tags.id')
$query = $this->pdo->from($this->tableName)
->innerJoin('postTags', 'postTags.tagId = tags.id')
->where('postTags.postId', $postIds);
$arrayEntities = iterator_to_array($query);
return $this->arrayToEntities($arrayEntities);
@ -52,11 +51,10 @@ class TagDao extends AbstractDao implements ICrudDao
if (!$tag)
return [];
$tagId = $tag->getId();
$query = $this->fpdo->from($this->tableName)
$query = $this->pdo->from($this->tableName)
->select('COUNT(pt2.postId) AS postCount')
->disableSmartJoin()
->innerJoin('postTags pt1 ON pt1.tagId = tags.id')
->innerJoin('postTags pt2 ON pt2.postId = pt1.postId')
->innerJoin('postTags pt1', 'pt1.tagId = tags.id')
->innerJoin('postTags pt2', 'pt2.postId = pt1.postId')
->where('pt2.tagId', $tagId)
->groupBy('tags.id')
->orderBy('postCount DESC, name ASC');
@ -79,7 +77,7 @@ class TagDao extends AbstractDao implements ICrudDao
public function export()
{
$exported = [];
foreach ($this->fpdo->from('tags') as $arrayEntity)
foreach ($this->pdo->from($this->tableName) as $arrayEntity)
{
$exported[$arrayEntity['id']] = [
'name' => $arrayEntity['name'],
@ -91,7 +89,7 @@ class TagDao extends AbstractDao implements ICrudDao
//upgrades on old databases
try
{
$relations = iterator_to_array($this->fpdo->from('tagRelations'));
$relations = iterator_to_array($this->pdo->from('tagRelations'));
}
catch (\Exception $e)
{
@ -160,7 +158,7 @@ class TagDao extends AbstractDao implements ICrudDao
elseif ($requirement->getType() === TagFilter::REQUIREMENT_CATEGORY)
{
$sql = 'IFNULL(category, \'default\') = ?';
$sql = 'IFNULL(category, \'default\')';
$requirement->setType($sql);
return parent::decorateQueryFromRequirement($query, $requirement);
}
@ -190,7 +188,7 @@ class TagDao extends AbstractDao implements ICrudDao
private function syncRelatedTagsByType(Tag $tag, array $relatedTags, $type)
{
$this->fpdo->deleteFrom('tagRelations')
$this->pdo->deleteFrom('tagRelations')
->where('tag1id', $tag->getId())
->where('type', $type)
->execute();
@ -206,7 +204,7 @@ class TagDao extends AbstractDao implements ICrudDao
foreach ($relatedTagIds as $tagId)
{
$this->fpdo
$this->pdo
->insertInto('tagRelations')
->values([
'tag1id' => $tag->getId(),
@ -219,9 +217,8 @@ class TagDao extends AbstractDao implements ICrudDao
private function findRelatedTagsByType(Tag $tag, $type)
{
$tagId = $tag->getId();
$query = $this->fpdo->from($this->tableName)
->disableSmartJoin()
->innerJoin('tagRelations tr ON tags.id = tr.tag2id')
$query = $this->pdo->from($this->tableName)
->innerJoin('tagRelations tr', 'tags.id = tr.tag2id')
->where('tr.type', $type)
->where('tr.tag1id', $tagId);
$arrayEntities = iterator_to_array($query);

View file

@ -20,7 +20,7 @@ class TokenDao extends AbstractDao
public function findByAdditionalDataAndPurpose($additionalData, $purpose)
{
$query = $this->fpdo->from($this->tableName)
$query = $this->pdo->from($this->tableName)
->where('additionalData', $additionalData)
->where('purpose', $purpose);
$arrayEntities = iterator_to_array($query);

View file

@ -52,7 +52,7 @@ class UserDao extends AbstractDao implements ICrudDao
public function deleteByName($userName)
{
$this->deleteBy('name', $userName);
$this->fpdo->deleteFrom('tokens')->where('additionalData', $userName);
$this->pdo->deleteFrom('tokens')->where('additionalData', $userName);
}
protected function afterLoad(Entity $user)

View file

@ -1,6 +1,7 @@
<?php
namespace Szurubooru;
use Szurubooru\Config;
use Szurubooru\PDOEx\PDOEx;
class DatabaseConnection
{

174
src/PDOEx/BaseQuery.php Normal file
View file

@ -0,0 +1,174 @@
<?php
namespace Szurubooru\PDOEx;
abstract class BaseQuery implements \IteratorAggregate
{
const CLAUSE_BASE = 'base';
const CLAUSE_WHERE = 'where';
const CLAUSE_JOIN = 'join';
const CLAUSE_ORDER = 'order';
const CLAUSE_GROUP = 'group';
const CLAUSE_LIMIT = 'limit';
protected $table;
protected $pdoex;
protected $clauses;
protected $parameters;
public function __construct(PDOEx $pdoex, $table)
{
$this->pdoex = $pdoex;
$this->table = $table;
$this->clauses = [];
$this->parameters = [];
$this->init();
}
public function getIterator()
{
return $this->execute();
}
public function getQuery()
{
return $this->buildQuery();
}
public function execute()
{
$query = $this->buildQuery();
$parameters = $this->getParameters();
try
{
$result = $this->pdoex->prepare($query);
if (!$result || !$result->execute($parameters))
$this->throwQueryException($query, $parameters, 'unknown reason');
}
catch (\PDOException $e)
{
$this->throwQueryException($query, $parameters, $e->getMessage());
}
return $result;
}
public function innerJoin($table, $condition)
{
if (!isset($this->clauses[self::CLAUSE_JOIN]))
$this->clauses[self::CLAUSE_JOIN] = [];
$this->clauses[self::CLAUSE_JOIN][] = 'INNER JOIN ' . $table . ' ON ' . $condition;
return $this;
}
public function where($key, $value = null)
{
if ($key === null)
{
$this->clauses[self::CLAUSE_WHERE] = [];
return;
}
if (!isset($this->clauses[self::CLAUSE_WHERE]))
$this->clauses[self::CLAUSE_WHERE] = [];
$sql = empty($this->clauses[self::CLAUSE_WHERE]) ? 'WHERE' : 'AND';
if (strpos($key, '?') !== false)
{
if (!is_array($value))
$value = [$value];
assert(substr_count($key, '?') === count($value), 'Binding ' . print_r($value, true) . ' to ' . $key);
$index = 0;
$sql .= ' ' . preg_replace_callback(
'/\?/',
function($match) use (&$index, $value)
{
$ret = $this->bind($value[$index]);
$index ++;
return $ret;
},
$key);
$this->clauses[self::CLAUSE_WHERE][] = $sql;
return $this;
}
if (!is_array($value))
{
if ($value === null)
$sql .= ' ' . $key . ' IS NULL';
else
$sql .= ' ' . $key . ' = ' . $this->bind($value);
$this->clauses[self::CLAUSE_WHERE][] = $sql;
return $this;
}
if (empty($value))
{
$sql .= ' 0';
$this->clauses[self::CLAUSE_WHERE][] = $sql;
return $this;
}
$sql .= ' ' . $key . ' IN (';
foreach ($value as $id => $val)
{
$sql .= $this->bind($val) . ', ';
}
$sql = substr($sql, 0, -2);
$sql .= ')';
$this->clauses[self::CLAUSE_WHERE][] = $sql;
return $this;
}
protected function getParameters()
{
return $this->parameters;
}
protected function buildQuery()
{
$priorities = array_flip([
self::CLAUSE_BASE,
self::CLAUSE_JOIN,
self::CLAUSE_WHERE,
self::CLAUSE_GROUP,
self::CLAUSE_ORDER,
self::CLAUSE_LIMIT]);
uksort(
$this->clauses,
function($clauseNameA, $clauseNameB) use ($priorities)
{
return $priorities[$clauseNameA] - $priorities[$clauseNameB];
});
$query = '';
foreach ($this->clauses as $statements)
{
if (!is_array($statements))
$statements = [$statements];
foreach ($statements as $statement)
$query .= ' ' . $statement;
}
return trim($query);
}
protected abstract function init();
protected function bind($value)
{
$id = ':' . uniqid();
$this->parameters[$id] = $value;
return $id;
}
private function throwQueryException($query, $parameters, $message)
{
throw new \Exception(sprintf(
'Problem executing query "%s" with parameters %s: %s',
$query,
print_r($parameters, true),
$message));
}
}

10
src/PDOEx/DeleteQuery.php Normal file
View file

@ -0,0 +1,10 @@
<?php
namespace Szurubooru\PDOEx;
class DeleteQuery extends BaseQuery
{
protected function init()
{
$this->clauses[self::CLAUSE_BASE] = 'DELETE FROM ' . $this->table;
}
}

41
src/PDOEx/InsertQuery.php Normal file
View file

@ -0,0 +1,41 @@
<?php
namespace Szurubooru\PDOEx;
class InsertQuery extends BaseQuery
{
private $values = [];
public function values(array $values)
{
$this->values = $values;
$this->refreshBaseQuery();
return $this;
}
public function where($key, $value = null)
{
throw new \BadMethodCallException('This makes no sense!');
}
public function innerJoin($table, $condition)
{
throw new \BadMethodCallException('This makes no sense!');
}
protected function init()
{
$this->refreshBaseQuery();
}
private function refreshBaseQuery()
{
$sql = 'INSERT INTO ' . $this->table;
$sql .= ' (' . implode(', ', array_keys($this->values)) . ')';
$sql .= ' VALUES (';
foreach ($this->values as $value)
$sql .= $this->bind($value) . ', ';
$sql = substr($sql, 0, -2);
$sql .= ')';
$this->clauses[self::CLAUSE_BASE] = $sql;
}
}

View file

@ -1,5 +1,5 @@
<?php
namespace Szurubooru;
namespace Szurubooru\PDOEx;
class PDOEx extends \PDO
{
@ -22,4 +22,24 @@ class PDOEx extends \PDO
{
return $this->statements;
}
public function from($table)
{
return new SelectQuery($this, $table);
}
public function insertInto($table)
{
return new InsertQuery($this, $table);
}
public function update($table)
{
return new UpdateQuery($this, $table);
}
public function deleteFrom($table)
{
return new DeleteQuery($this, $table);
}
}

95
src/PDOEx/SelectQuery.php Normal file
View file

@ -0,0 +1,95 @@
<?php
namespace Szurubooru\PDOEx;
class SelectQuery extends BaseQuery implements \Countable
{
private $selectTarget = '';
private $orderTarget = '';
private $offset = 0;
private $limit = null;
public function limit($limit)
{
if ($limit === null or $limit === false)
$this->limit = null;
else
$this->limit = intval($limit);
$this->refreshLimitClause();
return $this;
}
public function offset($offset)
{
$this->offset = intval($offset);
$this->refreshLimitClause();
return $this;
}
public function select($key)
{
if ($key === null)
$this->selectTarget = '';
else
{
if ($this->selectTarget)
$this->selectTarget .= ', ';
$this->selectTarget .= $key;
}
$this->refreshBaseClause();
return $this;
}
public function orderBy($key, $dir = null)
{
if ($key === null)
$this->orderTarget = '';
else
{
if ($this->orderTarget)
$this->orderTarget .= ', ';
$this->orderTarget .= rtrim($key . ' ' . $dir);
}
$this->refreshOrderClause();
return $this;
}
public function groupBy($key)
{
$this->clauses[self::CLAUSE_GROUP] = 'GROUP BY ' . $key;
return $this;
}
public function count()
{
$query = clone($this);
return iterator_to_array($query->select(null)->select('COUNT(1) AS c'))[0]['c'];
}
protected function init()
{
$this->selectTarget = $this->table . '.*';
$this->refreshBaseClause();
}
private function refreshBaseClause()
{
$this->clauses[self::CLAUSE_BASE] = 'SELECT ' . $this->selectTarget . ' FROM ' . $this->table;
}
private function refreshOrderClause()
{
$this->clauses[self::CLAUSE_ORDER] = 'ORDER BY ' . $this->orderTarget;
}
private function refreshLimitClause()
{
$sql = '';
if ($this->limit !== null)
{
$sql .= 'LIMIT ' . $this->limit;
if ($this->offset !== null and $this->offset !== 0)
$sql .= ' OFFSET ' . intval($this->offset);
}
$this->clauses[self::CLAUSE_LIMIT] = $sql;
}
}

34
src/PDOEx/UpdateQuery.php Normal file
View file

@ -0,0 +1,34 @@
<?php
namespace Szurubooru\PDOEx;
class UpdateQuery extends BaseQuery
{
private $values = [];
public function set(array $values)
{
$this->values = $values;
$this->refreshBaseQuery();
return $this;
}
public function innerJoin($table, $condition)
{
throw new \BadMethodCallException('This makes no sense!');
}
protected function init()
{
$this->refreshBaseQuery();
}
private function refreshBaseQuery()
{
$sql = 'UPDATE ' . $this->table;
$sql .= ' SET ';
foreach ($this->values as $key => $value)
$sql .= $key . ' = ' . $this->bind($value) . ', ';
$sql = substr($sql, 0, -2);
$this->clauses[self::CLAUSE_BASE] = $sql;
}
}

View file

@ -4,6 +4,12 @@ namespace Szurubooru\SearchServices\Requirements;
class RequirementCompositeValue implements IRequirementValue
{
private $values = [];
public function __construct(array $values = [])
{
$this->setValues($values);
}
public function getValues()
{
return $this->values;

View file

@ -145,6 +145,29 @@ final class PostDaoTest extends AbstractDatabaseTestCase
$this->assertEquals(1, count($postDao->findAll()));
}
public function testFindingByTagName()
{
$tag1 = new Tag();
$tag1->setName('tag1');
$tag1->setCreationTime(date('c'));
$tag2 = new Tag();
$tag2->setName('tag2');
$tag2->setCreationTime(date('c'));
$this->tagDao->save($tag1);
$this->tagDao->save($tag2);
$postDao = $this->getPostDao();
$post1 = self::getTestPost();
$post1->setTags([$tag1]);
$postDao->save($post1);
$post2 = self::getTestPost();
$post2->setTags([$tag2]);
$postDao->save($post2);
$this->assertEntitiesEqual([$post1], array_values($postDao->findByTagName('tag1')));
$this->assertEntitiesEqual([$post2], array_values($postDao->findByTagName('tag2')));
}
public function testSavingTags()
{
$tag1 = new Tag();

View file

@ -5,6 +5,7 @@ use Szurubooru\Entities\Tag;
use Szurubooru\SearchServices\Filters\TagFilter;
use Szurubooru\SearchServices\Requirements\Requirement;
use Szurubooru\SearchServices\Requirements\RequirementSingleValue;
use Szurubooru\SearchServices\Requirements\RequirementCompositeValue;
use Szurubooru\SearchServices\Result;
use Szurubooru\Tests\AbstractDatabaseTestCase;
@ -34,6 +35,30 @@ final class TagDaoFilterTest extends AbstractDatabaseTestCase
$this->assertEntitiesEqual([$tag3, $tag1], array_values($result->getEntities()));
}
public function testCompositeCategories()
{
$tag1 = $this->getTestTag('test 1');
$tag2 = $this->getTestTag('test 2');
$tag3 = $this->getTestTag('test 3');
$tag1->setCategory(null);
$tag2->setCategory('misc');
$tag3->setCategory('other');
$tagDao = $this->getTagDao();
$tagDao->save($tag1);
$tagDao->save($tag2);
$tagDao->save($tag3);
$searchFilter = new TagFilter();
$requirement = new Requirement();
$requirement->setType(TagFilter::REQUIREMENT_CATEGORY);
$requirement->setValue(new RequirementCompositeValue(['misc', 'other']));
$requirement->setNegated(true);
$searchFilter->addRequirement($requirement);
$result = $tagDao->findFiltered($searchFilter);
$this->assertEquals(1, $result->getTotalRecords());
$this->assertEntitiesEqual([$tag1], array_values($result->getEntities()));
}
private function getTagDao()
{
return new TagDao($this->databaseConnection);

View file

@ -0,0 +1,27 @@
<?php
namespace Szurubooru\Tests\PDOEx;
use Szurubooru\PDOEx\DeleteQuery;
use Szurubooru\PDOEx\PDOEx;
use Szurubooru\Tests\AbstractTestCase;
final class DeleteQueryTest extends AbstractTestCase
{
public function testDefault()
{
$query = $this->getDeleteQuery();
$this->assertEquals('DELETE FROM test', $query->getQuery());
}
public function testBasicWhere()
{
$query = $this->getDeleteQuery();
$query->where('column', 'value');
$this->assertRegExp('/^DELETE FROM test WHERE column = :[\w]*$/', $query->getQuery());
}
private function getDeleteQuery()
{
$pdoMock = $this->mock(PDOEx::class);
return new DeleteQuery($pdoMock, 'test');
}
}

View file

@ -0,0 +1,21 @@
<?php
namespace Szurubooru\Tests\PDOEx;
use Szurubooru\PDOEx\InsertQuery;
use Szurubooru\PDOEx\PDOEx;
use Szurubooru\Tests\AbstractTestCase;
final class InsertQueryTest extends AbstractTestCase
{
public function testDefault()
{
$query = $this->getInsertQuery();
$query->values(['key1' => 'value', 'key2' => 'value2']);
$this->assertRegExp('/^INSERT INTO test \(key1, key2\) VALUES \(:\w*, :\w*\)$/', $query->getQuery());
}
private function getInsertQuery()
{
$pdoMock = $this->mock(PDOEx::class);
return new InsertQuery($pdoMock, 'test');
}
}

View file

@ -0,0 +1,188 @@
<?php
namespace Szurubooru\Tests\PDOEx;
use Szurubooru\PDOEx\PDOEx;
use Szurubooru\PDOEx\SelectQuery;
use Szurubooru\Tests\AbstractTestCase;
final class SelectQueryTest extends AbstractTestCase
{
public function testDefault()
{
$query = $this->getSelectQuery();
$this->assertEquals('SELECT test.* FROM test', $query->getQuery());
}
public function testAdditionalColumns()
{
$query = $this->getSelectQuery();
$query->select('SUM(1) AS sum');
$query->select('something else');
$this->assertEquals('SELECT test.*, SUM(1) AS sum, something else FROM test', $query->getQuery());
}
public function testResettingAdditionalColumns()
{
$query = $this->getSelectQuery();
$query->select(null);
$query->select('SUM(1) AS sum');
$this->assertEquals('SELECT SUM(1) AS sum FROM test', $query->getQuery());
}
public function testInnerJoin()
{
$query = $this->getSelectQuery();
$query->innerJoin('test2', 'test2.id = test.foreignId');
$this->assertEquals('SELECT test.* FROM test INNER JOIN test2 ON test2.id = test.foreignId', $query->getQuery());
}
public function testMultipleInnerJoins()
{
$query = $this->getSelectQuery();
$query->innerJoin('test2', 'test2.id = test.foreignId');
$query->innerJoin('test3', 'test3.id = test2.foreignId');
$this->assertEquals('SELECT test.* FROM test INNER JOIN test2 ON test2.id = test.foreignId INNER JOIN test3 ON test3.id = test2.foreignId', $query->getQuery());
}
public function testSelectAfterInnerJoin()
{
$query = $this->getSelectQuery();
$query->innerJoin('test2', 'test2.id = test.foreignId');
$query->select('whatever');
$this->assertEquals('SELECT test.*, whatever FROM test INNER JOIN test2 ON test2.id = test.foreignId', $query->getQuery());
}
public function testBasicWhere()
{
$query = $this->getSelectQuery();
$query->where('column', 'value');
$this->assertRegExp('/^SELECT test\.\* FROM test WHERE column = :[\w]*$/', $query->getQuery());
}
public function testMultipleWhere()
{
$query = $this->getSelectQuery();
$query->where('column1', 'value1');
$query->where('column2', 'value2');
$this->assertRegExp('/^SELECT test\.\* FROM test WHERE column1 = :\w* AND column2 = :\w*$/', $query->getQuery());
}
public function testManualWhere()
{
$query = $this->getSelectQuery();
$query->where('column1 >= ? AND column2 <= ?', ['value1', 'value2']);
$this->assertRegExp('/^SELECT test\.\* FROM test WHERE column1 >= :\w* AND column2 <= :\w*$/', $query->getQuery());
}
public function testWhereNull()
{
$query = $this->getSelectQuery();
$query->where('column', null);
$this->assertRegExp('/^SELECT test\.\* FROM test WHERE column IS NULL$/', $query->getQuery());
}
public function testResettingWhere()
{
$query = $this->getSelectQuery();
$query->where('column1', 'value1');
$query->where(null);
$query->where('column2', 'value2');
$this->assertRegExp('/^SELECT test\.\* FROM test WHERE column2 = :\w*$/', $query->getQuery());
}
public function testEmptyIn()
{
$query = $this->getSelectQuery();
$query->where('column', []);
$this->assertRegExp('/^SELECT test\.\* FROM test WHERE 0$/', $query->getQuery());
}
public function testIn()
{
$query = $this->getSelectQuery();
$query->where('column', ['val1', 'val2']);
$this->assertRegExp('/^SELECT test\.\* FROM test WHERE column IN \(:\w*, :\w*\)$/', $query->getQuery());
}
public function testMixedInAndWhere()
{
$query = $this->getSelectQuery();
$query->where('column1', ['val1', 'val2']);
$query->where('column2', 'val3');
$this->assertRegExp('/^SELECT test\.\* FROM test WHERE column1 IN \(:\w*, :\w*\) AND column2 = :\w*$/', $query->getQuery());
}
public function testGroupBy()
{
$query = $this->getSelectQuery();
$query->groupBy('test.id');
$this->assertEquals('SELECT test.* FROM test GROUP BY test.id', $query->getQuery());
}
public function testGroupByAndOrderBy()
{
$query = $this->getSelectQuery();
$query->groupBy('test.id');
$query->orderBy('test.whatever');
$this->assertEquals('SELECT test.* FROM test GROUP BY test.id ORDER BY test.whatever', $query->getQuery());
}
public function testOrderBy()
{
$query = $this->getSelectQuery();
$query->orderBy('id DESC');
$this->assertEquals('SELECT test.* FROM test ORDER BY id DESC', $query->getQuery());
}
public function testOrderByFlavor2()
{
$query = $this->getSelectQuery();
$query->orderBy('id', 'DESC');
$this->assertEquals('SELECT test.* FROM test ORDER BY id DESC', $query->getQuery());
}
public function testOrderByMultiple()
{
$query = $this->getSelectQuery();
$query->orderBy('id', 'DESC');
$query->orderBy('id2', 'ASC');
$this->assertEquals('SELECT test.* FROM test ORDER BY id DESC, id2 ASC', $query->getQuery());
}
public function testResettingOrderBy()
{
$query = $this->getSelectQuery();
$query->orderBy('id', 'DESC');
$query->orderBy(null);
$query->orderBy('id2', 'ASC');
$this->assertEquals('SELECT test.* FROM test ORDER BY id2 ASC', $query->getQuery());
}
public function testLimit()
{
$query = $this->getSelectQuery();
$query->limit(5);
$this->assertEquals('SELECT test.* FROM test LIMIT 5', $query->getQuery());
}
public function testLimitWithOffset()
{
$query = $this->getSelectQuery();
$query->offset(2);
$query->limit(5);
$this->assertEquals('SELECT test.* FROM test LIMIT 5 OFFSET 2', $query->getQuery());
}
public function testOffsetWithoutLimit()
{
$query = $this->getSelectQuery();
$query->offset(2);
$query->limit(null);
$this->assertEquals('SELECT test.* FROM test', $query->getQuery());
}
private function getSelectQuery()
{
$pdoMock = $this->mock(PDOEx::class);
return new SelectQuery($pdoMock, 'test');
}
}

View file

@ -0,0 +1,21 @@
<?php
namespace Szurubooru\Tests\PDOEx;
use Szurubooru\PDOEx\PDOEx;
use Szurubooru\PDOEx\UpdateQuery;
use Szurubooru\Tests\AbstractTestCase;
final class UpdateQueryTest extends AbstractTestCase
{
public function testDefault()
{
$query = $this->getUpdateQuery();
$query->set(['key1' => 'value', 'key2' => 'value2']);
$this->assertRegExp('/^UPDATE test SET key1 = :\w*, key2 = :\w*$/', $query->getQuery());
}
private function getUpdateQuery()
{
$pdoMock = $this->mock(PDOEx::class);
return new UpdateQuery($pdoMock, 'test');
}
}