SilverFire - Dmitry Naumenko
7 years ago
6 changed files with 202 additions and 1 deletions
@ -0,0 +1,115 @@
|
||||
<?php |
||||
|
||||
namespace yii\db\conditions; |
||||
|
||||
use yii\base\InvalidArgumentException; |
||||
use yii\db\ExpressionInterface; |
||||
use yii\db\Query; |
||||
|
||||
/** |
||||
* Class BetweenColumnCondition represents a `BETWEEN` condition where |
||||
* values is between two columns. For example: |
||||
* |
||||
* ```php |
||||
* new BetweenColumnsCondition(42, 'BETWEEN', 'min_value', 'max_value') |
||||
* // Will be build to: |
||||
* // 42 BETWEEN min_value AND max_value |
||||
* ``` |
||||
* |
||||
* And a more complex example: |
||||
* |
||||
* ```php |
||||
* new BetweenColumnsCondition( |
||||
* new Expression('NOW()'), |
||||
* 'NOT BETWEEN', |
||||
* (new Query)->select('time')->from('log')->orderBy('id ASC')->limit(1), |
||||
* 'update_time' |
||||
* ); |
||||
* |
||||
* // Will be built to: |
||||
* // NOW() BETWEEN (SELECT time FROM log ORDER BY id ASC LIMIT 1) AND update_time |
||||
* ``` |
||||
* |
||||
* @author Dmytro Naumenko <d.naumenko.a@gmail.com> |
||||
* @since 2.0.14 |
||||
*/ |
||||
class BetweenColumnsCondition implements ConditionInterface |
||||
{ |
||||
/** |
||||
* @var string $operator the operator to use (e.g. `BETWEEN` or `NOT BETWEEN`) |
||||
*/ |
||||
protected $operator; |
||||
/** |
||||
* @var mixed the value to compare against |
||||
*/ |
||||
protected $value; |
||||
/** |
||||
* @var string|ExpressionInterface|Query the column name or expression that is a beginning of the interval |
||||
*/ |
||||
protected $intervalStartColumn; |
||||
/** |
||||
* @var string|ExpressionInterface|Query the column name or expression that is an end of the interval |
||||
*/ |
||||
protected $intervalEndColumn; |
||||
|
||||
/** |
||||
* Creates a condition with the `BETWEEN` operator. |
||||
* |
||||
* @param mixed the value to compare against |
||||
* @param string $operator the operator to use (e.g. `BETWEEN` or `NOT BETWEEN`) |
||||
* @param string|ExpressionInterface $intervalStartColumn the column name or expression that is a beginning of the interval |
||||
* @param string|ExpressionInterface $intervalEndColumn the column name or expression that is an end of the interval |
||||
*/ |
||||
public function __construct($value, $operator, $intervalStartColumn, $intervalEndColumn) |
||||
{ |
||||
$this->value = $value; |
||||
$this->operator = $operator; |
||||
$this->intervalStartColumn = $intervalStartColumn; |
||||
$this->intervalEndColumn = $intervalEndColumn; |
||||
} |
||||
|
||||
/** |
||||
* @return string |
||||
*/ |
||||
public function getOperator() |
||||
{ |
||||
return $this->operator; |
||||
} |
||||
|
||||
/** |
||||
* @return mixed |
||||
*/ |
||||
public function getValue() |
||||
{ |
||||
return $this->value; |
||||
} |
||||
|
||||
/** |
||||
* @return string|ExpressionInterface|Query |
||||
*/ |
||||
public function getIntervalStartColumn() |
||||
{ |
||||
return $this->intervalStartColumn; |
||||
} |
||||
|
||||
/** |
||||
* @return string|ExpressionInterface|Query |
||||
*/ |
||||
public function getIntervalEndColumn() |
||||
{ |
||||
return $this->intervalEndColumn; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
* @throws InvalidArgumentException if wrong number of operands have been given. |
||||
*/ |
||||
public static function fromArrayDefinition($operator, $operands) |
||||
{ |
||||
if (!isset($operands[0], $operands[1], $operands[2])) { |
||||
throw new InvalidArgumentException("Operator '$operator' requires three operands."); |
||||
} |
||||
|
||||
return new static($operands[0], $operator, $operands[1], $operands[2]); |
||||
} |
||||
} |
@ -0,0 +1,75 @@
|
||||
<?php |
||||
|
||||
namespace yii\db\conditions; |
||||
|
||||
use yii\db\ExpressionBuilderInterface; |
||||
use yii\db\ExpressionBuilderTrait; |
||||
use yii\db\ExpressionInterface; |
||||
use yii\db\Query; |
||||
|
||||
/** |
||||
* Class BetweenColumnsConditionBuilder builds objects of [[BetweenColumnsCondition]] |
||||
* |
||||
* @author Dmytro Naumenko <d.naumenko.a@gmail.com> |
||||
* @since 2.0.14 |
||||
*/ |
||||
class BetweenColumnsConditionBuilder implements ExpressionBuilderInterface |
||||
{ |
||||
use ExpressionBuilderTrait; |
||||
|
||||
/** |
||||
* Method builds the raw SQL from the $expression that will not be additionally |
||||
* escaped or quoted. |
||||
* |
||||
* @param ExpressionInterface|BetweenColumnsCondition $expression the expression to be built. |
||||
* @param array $params the binding parameters. |
||||
* @return string the raw SQL that will not be additionally escaped or quoted. |
||||
*/ |
||||
public function build(ExpressionInterface $expression, array &$params = []) |
||||
{ |
||||
$operator = $expression->getOperator(); |
||||
|
||||
$startColumn = $this->escapeColumnName($expression->getIntervalStartColumn(), $params); |
||||
$endColumn = $this->escapeColumnName($expression->getIntervalEndColumn(), $params); |
||||
$value = $this->createPlaceholder($expression->getValue(), $params); |
||||
|
||||
return "$value $operator $startColumn AND $endColumn"; |
||||
} |
||||
|
||||
/** |
||||
* Prepares column name to be used in SQL statement. |
||||
* |
||||
* @param Query|ExpressionInterface|string $columnName |
||||
* @param array $params the binding parameters. |
||||
* @return string |
||||
*/ |
||||
protected function escapeColumnName($columnName, &$params = []) |
||||
{ |
||||
if ($columnName instanceof Query) { |
||||
list($sql, $params) = $this->queryBuilder->build($columnName, $params); |
||||
return "($sql)"; |
||||
} elseif ($columnName instanceof ExpressionInterface) { |
||||
return $this->queryBuilder->buildExpression($columnName, $params); |
||||
} elseif (strpos($columnName, '(') === false) { |
||||
return $this->queryBuilder->db->quoteColumnName($columnName); |
||||
} |
||||
|
||||
return $columnName; |
||||
} |
||||
|
||||
/** |
||||
* Attaches $value to $params array and returns placeholder. |
||||
* |
||||
* @param mixed $value |
||||
* @param array $params passed by reference |
||||
* @return string |
||||
*/ |
||||
protected function createPlaceholder($value, &$params) |
||||
{ |
||||
if ($value instanceof ExpressionInterface) { |
||||
return $this->queryBuilder->buildExpression($value, $params); |
||||
} |
||||
|
||||
return $this->queryBuilder->bindParam($value, $params); |
||||
} |
||||
} |
Loading…
Reference in new issue