Skip to content

Commit

Permalink
Add method Selection::havingOr
Browse files Browse the repository at this point in the history
  • Loading branch information
dakujem committed Nov 26, 2019
1 parent 8c81bf3 commit 30f8fa0
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 17 deletions.
58 changes: 41 additions & 17 deletions src/Database/Table/Selection.php
Original file line number Diff line number Diff line change
Expand Up @@ -355,23 +355,7 @@ public function whereOr(array $parameters)
if (count($parameters) < 2) {
return $this->where($parameters);
}
$columns = [];
$values = [];
foreach ($parameters as $key => $val) {
if (is_int($key)) { // whereOr(['full condition'])
$columns[] = $val;
} elseif (strpos($key, '?') === false) { // whereOr(['column1' => 1])
$columns[] = $key . ' ?';
$values[] = $val;
} else { // whereOr(['column1 > ?' => 1])
$qNumber = substr_count($key, '?');
if ($qNumber > 1 && (!is_array($val) || $qNumber !== count($val))) {
throw new Nette\InvalidArgumentException('Argument count does not match placeholder count.');
}
$columns[] = $key;
$values = array_merge($values, $qNumber > 1 ? $val : [$val]);
}
}
[$columns, $values] = $this->paramsOr($parameters);
$columnsString = '(' . implode(') OR (', $columns) . ')';
return $this->where($columnsString, $values);
}
Expand Down Expand Up @@ -442,6 +426,19 @@ public function having(string $having, ...$params)
}


/**
* Sets having clause, more calls rewrite old value.
* @param array $parameters ['column1' => 1, 'column2 > ?' => 2, 'full condition']
* @return static
*/
public function havingOr(array $parameters)
{
[$columns, $values] = $this->paramsOr($parameters);
$columnsString = count($columns) > 1 ? '(' . implode(') OR (', $columns) . ')' : implode('', $columns);
return $this->having($columnsString, $values);
}


/**
* Aliases table. Example ':book:book_tag.tag', 'tg'
* @return static
Expand Down Expand Up @@ -756,6 +753,33 @@ public function getDataRefreshed(): bool
}


/**
* @param array $parameters ['column1' => 1, 'column2 > ?' => 2, 'full condition']
* @return array [$columns, $values] to be used with `where` or `having`
*/
protected function paramsOr(array $parameters): array
{
$columns = [];
$values = [];
foreach ($parameters as $key => $val) {
if (is_int($key)) { // whereOr(['full condition'])
$columns[] = $val;
} elseif (strpos($key, '?') === FALSE) { // whereOr(['column1' => 1])
$columns[] = $key . ' ?';
$values[] = $val;
} else { // whereOr(['column1 > ?' => 1])
$qNumber = substr_count($key, '?');
if ($qNumber > 1 && (!is_array($val) || $qNumber !== count($val))) {
throw new Nette\InvalidArgumentException('Argument count does not match placeholder count.');
}
$columns[] = $key;
$values = array_merge($values, $qNumber > 1 ? $val : [$val]);
}
}
return [$columns, $values];
}


/********************* manipulation ****************d*g**/


Expand Down
106 changes: 106 additions & 0 deletions tests/Database/Table/Selection.havingOr().phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php

/**
* Test: Nette\Database\Table: WhereOr operations
* @dataProvider? ../databases.ini
*/

declare(strict_types=1);

use Tester\Assert;

require __DIR__ . '/../connect.inc.php'; // create $connection

Nette\Database\Helpers::loadFromFile($connection, __DIR__ . "/../files/{$driverName}-nette_test1.sql");

// without question mark
test(function () use ($context) {
$count = $context->table('book')->havingOr([
'author_id' => 12,
'title' => 'JUSH',
])->count();
Assert::same(3, $count);
});


// full condition
test(function () use ($context) {
$count = $context->table('book')->havingOr([
'translator_id IS NULL',
'title' => 'Dibi',
])->count();
Assert::same(2, $count);
});


// with question mark
test(function () use ($context) {
$count = $context->table('book')->havingOr([
'id > ?' => 3,
'translator_id' => 11,
])->count();
Assert::same(2, $count);
});


// just one condition
test(function () use ($context) {
$count = $context->table('book')->havingOr([
'id > ?' => 3,
])->count();
Assert::same(1, $count);
});


// with question mark
test(function () use ($context) {
$count = $context->table('book')->havingOr([
'id ?' => [3, 4],
'translator_id' => 11,
])->count();
Assert::same(3, $count);
});


// multiple values for one key
test(function () use ($context) {
$count = $context->table('author')->havingOr([
'id > ?' => 12,
'ROUND(id, ?) = ?' => [5, 3],
])->count();
Assert::same(1, $count);
});


// nested condition
test(function () use ($context) {
$books = $context->table('book')->havingOr([
'id = ?' => 4,
'author_id = ? AND translator_id ?' => [11, null],
]);
Assert::same(2, $books->count());
});


// invalid param count
test(function () use ($context) {
$f = function () use ($context) {
$context->table('author')->havingOr([
'id > ?' => 3,
'ROUND(id, ?) = ?' => [5],
])->count();
};
Assert::throws($f, Nette\InvalidArgumentException::class, 'Argument count does not match placeholder count.');
});


// invalid param count
test(function () use ($context) {
$f = function () use ($context) {
$context->table('author')->havingOr([
'id > ?' => 3,
'ROUND(id, ?) = ?' => 5,
])->count();
};
Assert::throws($f, Nette\InvalidArgumentException::class, 'Argument count does not match placeholder count.');
});

0 comments on commit 30f8fa0

Please sign in to comment.