Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion src/Expression.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,23 @@ class Expression implements ExpressionInterface
/** @var string The statement of the expression */
protected $statement;

/** @var array The columns used by the expression */
protected $columns;

/** @var array The values for the expression */
protected $values;

/**
* Create a new database expression
*
* @param string $statement The statement of the expression
* @param array $columns The columns used by the expression
* @param mixed ...$values The values for the expression
*/
public function __construct($statement, ...$values)
public function __construct($statement, array $columns = null, ...$values)
{
$this->statement = $statement;
$this->columns = $columns;
$this->values = $values;
}

Expand All @@ -30,6 +35,16 @@ public function getStatement()
return $this->statement;
}

public function getColumns()
{
return $this->columns ?: [];
}

public function setColumns(array $columns)
{
$this->columns = $columns;
}

public function getValues()
{
return $this->values;
Expand Down
16 changes: 16 additions & 0 deletions src/ExpressionInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,22 @@ interface ExpressionInterface
*/
public function getStatement();

/**
* Get the columns used by the expression
*
* @return array
*/
public function getColumns();

/**
* Set the columns to use by the expression
*
* @param array $columns
*
* @return $this
*/
public function setColumns(array $columns);

/**
* Get the values for the expression
*
Expand Down
39 changes: 27 additions & 12 deletions src/QueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -313,8 +313,7 @@ public function buildCondition(array $condition, array &$values)
}
} else {
if ($value instanceof ExpressionInterface) {
$sql[] = $value->getStatement();
$values = array_merge($values, $value->getValues());
$sql[] = $this->buildExpression($value, $values);
} elseif ($value instanceof Select) {
$stmt = '(' . $this->assembleSelect($value, $values)[0] . ')';
if (is_int($expression)) {
Expand Down Expand Up @@ -407,8 +406,7 @@ public function buildInsertColumnsAndValues(array $columns, array $insertValues,

foreach ($insertValues as $value) {
if ($value instanceof ExpressionInterface) {
$preparedValues[] = $value->getStatement();
$values = array_merge($values, $value->getValues());
$preparedValues[] = $this->buildExpression($value, $values);
} elseif ($value instanceof Select) {
$preparedValues[] = "({$this->assembleSelect($value, $values)[0]})";
} else {
Expand Down Expand Up @@ -451,8 +449,7 @@ public function buildSelect(array $columns, $distinct, array &$values)

foreach ($columns as $alias => $column) {
if ($column instanceof ExpressionInterface) {
$values = array_merge($values, $column->getValues());
$column = "({$column->getStatement()})";
$column = "({$this->buildExpression($column, $values)})";
} elseif ($column instanceof Select) {
$column = "({$this->assembleSelect($column, $values)[0]})";
}
Expand Down Expand Up @@ -559,8 +556,7 @@ public function buildGroupBy(array $groupBy = null, array &$values = [])

foreach ($groupBy as &$column) {
if ($column instanceof ExpressionInterface) {
$values = array_merge($values, $column->getValues());
$column = $column->getStatement();
$column = $this->buildExpression($column, $values);
} elseif ($column instanceof Select) {
$column = "({$this->assembleSelect($column, $values)[0]})";
}
Expand Down Expand Up @@ -606,8 +602,7 @@ public function buildOrderBy(array $orderBy = null, array &$values = [])
list($column, $direction) = $column;

if ($column instanceof ExpressionInterface) {
$values = array_merge($values, $column->getValues());
$column = $column->getStatement();
$column = $this->buildExpression($column, $values);
} elseif ($column instanceof Select) {
$column = "({$this->assembleSelect($column, $values)[0]})";
}
Expand Down Expand Up @@ -734,8 +729,7 @@ public function buildUpdateSet(array $set = null, array &$values = [])

foreach ($set as $column => $value) {
if ($value instanceof ExpressionInterface) {
$sql[] = "$column = {$value->getStatement()}";
$values = array_merge($values, $value->getValues());
$sql[] = "$column = {$this->buildExpression($value, $values)}";
} elseif ($value instanceof Select) {
$sql[] = "$column = ({$this->assembleSelect($value, $values)[0]})";
} else {
Expand All @@ -746,4 +740,25 @@ public function buildUpdateSet(array $set = null, array &$values = [])

return 'SET ' . implode(', ', $sql);
}

/**
* Build expression
*
* @param ExpressionInterface $expression
* @param array $values
*
* @return string The expression's statement
*/
public function buildExpression(ExpressionInterface $expression, array &$values = [])
{
$stmt = $expression->getStatement();
$columns = $expression->getColumns();
if (! empty($columns)) {
$stmt = vsprintf($stmt, $columns);
}

$values = array_merge($values, $expression->getValues());

return $stmt;
}
}
2 changes: 1 addition & 1 deletion tests/HavingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public function testHavingArrayFormat()

public function testWhereWithExpression()
{
$expression = new Expression('c2 = ?', 1);
$expression = new Expression('c2 = ?', null, 1);
$this->query->having($expression);

$this->assertCorrectStatementAndValues('HAVING c2 = ?', [1]);
Expand Down
2 changes: 1 addition & 1 deletion tests/InsertTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public function testValues()

public function testExpressionValue()
{
$value = new Expression('x = ?', 1);
$value = new Expression('x = ?', null, 1);
$this->query->values(['c1' => $value]);

$this->assertSame(['c1'], $this->query->getColumns());
Expand Down
14 changes: 7 additions & 7 deletions tests/SelectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public function testColumnsWithArrayAndAlias()

public function testColumnsWithExpression()
{
$columns = ['three' => new Expression('? + ?', 1, 2)];
$columns = ['three' => new Expression('? + ?', null, 1, 2)];
$this->query->columns($columns);

$this->assertSame($columns, $this->query->getColumns());
Expand Down Expand Up @@ -209,7 +209,7 @@ public function testInnerJoinWithSelect()

public function testInnerJoinWithExpressionCondition()
{
$condition = new Expression('t2.table1_id = ?', 1);
$condition = new Expression('t2.table1_id = ?', null, 1);
$this->query->join('table2', $condition);

$this->assertCorrectStatementAndValues('INNER JOIN table2 ON t2.table1_id = ?', [1]);
Expand Down Expand Up @@ -300,7 +300,7 @@ public function testLeftJoinWithSelect()

public function testLeftJoinWithExpressionCondition()
{
$condition = new Expression('t2.table1_id = ?', 1);
$condition = new Expression('t2.table1_id = ?', null, 1);
$this->query->joinLeft('table2', $condition);

$this->assertCorrectStatementAndValues('LEFT JOIN table2 ON t2.table1_id = ?', [1]);
Expand Down Expand Up @@ -391,7 +391,7 @@ public function testRightJoinWithSelect()

public function testRightJoinWithExpressionCondition()
{
$condition = new Expression('t2.table1_id = ?', 1);
$condition = new Expression('t2.table1_id = ?', null, 1);
$this->query->joinRight('table2', $condition);

$this->assertCorrectStatementAndValues('RIGHT JOIN table2 ON t2.table1_id = ?', [1]);
Expand Down Expand Up @@ -424,7 +424,7 @@ public function testGroupByWithAlias()

public function testGroupByWithExpression()
{
$column = new Expression('x = ?', 1);
$column = new Expression('x = ?', null, 1);
$this->query->groupBy([$column]);

$this->assertCorrectStatementAndValues('GROUP BY x = ?', [1]);
Expand All @@ -447,15 +447,15 @@ public function testOrderBy()

public function testOrderByWithExpression()
{
$column = new Expression('x = ?', 1);
$column = new Expression('x = ?', null, 1);
$this->query->orderBy($column, 'DESC');

$this->assertCorrectStatementAndValues('ORDER BY x = ? DESC', [1]);
}

public function testOrderByWithExpressionAndExplicitDirection()
{
$column = new Expression('x = ?', 1);
$column = new Expression('x = ?', null, 1);
$this->query->orderBy([[$column, 'DESC']]);

$this->assertCorrectStatementAndValues('ORDER BY x = ? DESC', [1]);
Expand Down
2 changes: 1 addition & 1 deletion tests/UpdateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public function testSet()

public function testExpressionValue()
{
$value = new Expression('x = ?', 1);
$value = new Expression('x = ?', null, 1);
$this->query->set(['c1' => $value]);

$this->assertSame(['c1' => $value], $this->query->getSet());
Expand Down
2 changes: 1 addition & 1 deletion tests/WhereTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ public function testPartiallyPreparedWhere()

public function testWhereWithExpression()
{
$expression = new Expression('c2 = ?', 1);
$expression = new Expression('c2 = ?', null, 1);
$this->query->where($expression);

$this->assertCorrectStatementAndValues('WHERE c2 = ?', [1]);
Expand Down