Skip to content

Commit

Permalink
Add builder/grammar support for row values in where condition
Browse files Browse the repository at this point in the history
  • Loading branch information
mfn committed Dec 15, 2017
1 parent 13ee3f1 commit dedec48
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 0 deletions.
41 changes: 41 additions & 0 deletions src/Illuminate/Database/Query/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -1237,6 +1237,47 @@ public function addWhereExistsQuery(self $query, $boolean = 'and', $not = false)
return $this;
}

/**
* Adds a where condition using row values.
*
* This is mostly used with "keyset pagination" aka "seek method".
*
* @param array $columns
* @param string $operator
* @param array $values
* @param string $boolean
* @return $this
*/
public function whereRowValues($columns, $operator, $values, $boolean = 'and')
{
if (count($columns) != count($values)) {
throw new InvalidArgumentException('The number of columns must match the number of values');
}

$type = 'RowValues';

$this->wheres[] = compact('type', 'columns', 'operator', 'values', 'boolean');

$this->addBinding($values);

return $this;
}

/**
* Adds a or where condition using row values.
*
* This is mostly used with "keyset pagination" aka "seek method".
*
* @param array $columns
* @param string $operator
* @param array $values
* @return $this
*/
public function orWhereRowValues($columns, $operator, $values)
{
return $this->whereRowValues($columns, $operator, $values, 'or');
}

/**
* Handles dynamic "where" clauses to the query.
*
Expand Down
15 changes: 15 additions & 0 deletions src/Illuminate/Database/Query/Grammars/Grammar.php
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,21 @@ protected function whereNotExists(Builder $query, $where)
return 'not exists ('.$this->compileSelect($where['query']).')';
}

/**
* Compile a where row values condition.
*
* @param \Illuminate\Database\Query\Builder $query
* @param array $where
* @return string
*/
protected function whereRowValues(Builder $query, $where)
{
$columns = join(', ', $where['columns']);
$values = $this->parameterize($where['values']);

return '('.$columns.') '.$where['operator'].' ('.$values.')';
}

/**
* Compile the "group by" portions of the query.
*
Expand Down
20 changes: 20 additions & 0 deletions tests/Database/DatabaseQueryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2363,6 +2363,26 @@ public function testPaginateWhenNoResults()
]), $result);
}

public function testWhereRowValues()
{
$builder = $this->getBuilder();
$builder->select('*')->from('orders')->whereRowValues(['last_update', 'order_number'], '<', [1, 2]);
$this->assertEquals('select * from "orders" where (last_update, order_number) < (?, ?)', $builder->toSql());

$builder = $this->getBuilder();
$builder->select('*')->from('orders')->where('company_id', 1)->orWhereRowValues(['last_update', 'order_number'], '<', [1, 2]);
$this->assertEquals('select * from "orders" where "company_id" = ? or (last_update, order_number) < (?, ?)', $builder->toSql());
}

public function testWhereRowValuesArityMismatch()
{
$this->expectException('InvalidArgumentException');
$this->expectExceptionMessage('The number of columns must match the number of values');

$builder = $this->getBuilder();
$builder->select('*')->from('orders')->whereRowValues(['last_update'], '<', [1, 2]);
}

protected function getBuilder()
{
$grammar = new \Illuminate\Database\Query\Grammars\Grammar;
Expand Down

0 comments on commit dedec48

Please sign in to comment.